0

在高层次上,以下是我打算在这里发生的事情:

-- BackgroundManagerService 中的 BroadcastReceiver 接收来自 Android 的广播(工作正常)

-- BackgroundManagerService 中的 BroadcastReceiver 将意图发送到 startTestsRunnerThread()(工作正常)

-- startTestsRunnerThread() 创建一个 BackgroundTestRunnerThread 并启动它(似乎工作正常)

-- 作为BackgroundTestRunnerThread 的一个实例并且刚刚创建的线程被休眠60 秒(不起作用)。从广泛的日志记录中,当“BackgroundTestRunnerThread.sleep(milliseconds);” 被执行,它正在主线程中运行。

编辑:我从答案中意识到 sleep() 是一种静态方法,仅适用于当前线程。有没有办法将消息发送到正在运行 BackgroundTestRunnerThread 的线程并让它休眠(即,从另一个线程中调用 sleep)?

我意识到,根据https://stackoverflow.com/a/3072338/1783829和其他帖子,我可能应该使用 ScheduledExecutorService 执行此操作,但这不是我的问题。目前,我的问题是为什么 sleep() 在主线程而不是在单独的线程中执行。这导致 ANR(Android 无响应)并且 Android 杀死了我的应用程序。

这是我的完整代码:

public class Logger {
  public static void v(String tag, String msg) {
    Log.v(tag, Thread.currentThread().getName() + " **** " + msg);
  }
}


public class BackgroundTestRunnerThread extends Thread {
    @Override
    public void run() {
      try {
        while (!BackgroundTestRunnerThread.currentThread().isInterrupted()) {
          Intent intent = new Intent(MainActivity.getAppContext(), TestsRunnerService.class);
          Logger.v(this.getClass().getName(), "About to start TestsRunnerService ");
          MainActivity.getAppContext().startService(intent);

          SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(
              MainActivity.getAppContext());
          int sleepTime;
          // Since Android saves preferences as strings, even with 'android:numeric="integer"',
          // we need to convert to an integer.
          sleepTime = Integer.parseInt(settings.getString("pref_key_frequency", "60"));
          Logger.v(this.getClass().getName(), "Sleep thread for " + sleepTime + " seconds");
          BackgroundTestRunnerThread.sleep(sleepTime * 1000);
        }
      } catch (InterruptedException e) {
        Logger.v(this.getClass().getName(), "Thread interrupted ");
      } catch (Exception e) {
        Logger.v(this.getClass().getName(), "Thread exception: " + e.getMessage());
      }
    }

    public void cancel() {
      Logger.v(this.getClass().getName(), "About to cancel thread");
      interrupt();
    }

    public void pause(int milliseconds) {
      try {
        Logger.v(this.getClass().getName(), "About to sleep thread background runner");
        // Logging shows that this is running in MAIN and not in a separate thread.
        BackgroundTestRunnerThread.sleep(milliseconds);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
}


public class BackgroundManagerService extends Service {
  private volatile BackgroundTestRunnerThread testsRunnerThread;
  private BroadcastReceiver networkStatusChangedReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        BackgroundManagerService.this.startTestsRunnerThread(60); 
    }
  };

  private void startTestsRunnerThread(int secondsDelay) {
    if (testsRunnerThread == null || !testsRunnerThread.isAlive()) {
      testsRunnerThread = new BackgroundTestRunnerThread();
      Logger.v(this.getClass().getName(), "Sending start signal to     BackgroundTestRunnerThread");
      testsRunnerThread.start();
      Logger.v(this.getClass().getName(),
          "Sending start signal to BackgroundTestRunnerThread to sleep");
      testsRunnerThread.pause(secondsDelay * 1000);
      Logger.v(this.getClass().getName(), "Executed past sleep command");
    }
  }
}

在此处输入图像描述

4

4 回答 4

2

正如我所看到的,您已经知道 Thread.sleep 是静态方法,并且仅使当前运行的线程休眠,有两个地方您正在使用 sleep()。

  1. BackgroundTestRunnerThread.sleep(sleepTime * 1000); 在 run() 方法中:这不是问题,因为它总是在 BackgroundTestRunnerThread 线程中调用,而不是在主线程中。
  2. pause(int milliseconds) 方法:我看不到您的主线程代码,但您可能正在从 main 调用 pause 方法,假设它将使 BackgroundTestRunnerThread 线程休眠,但因为它可能是从主线程调用的,它会使主线程不休眠另一个。

希望这可以帮助。

于 2014-04-01T12:33:10.773 回答
1

sleep()是一个静态方法,Thread并且总是使当前线程休眠,即使您尝试在线程对象上调用它。这也会给你一个编译器警告:

The static method sleep(long) from the type Thread should be accessed in a static way

有没有办法将消息发送到正在运行 BackgroundTestRunnerThread 的线程并让它休眠(即,从另一个线程中调用 sleep)?

线程之间通信的规范方法是使用 aHandler和 a Looper

此外,出于调度目的,请考虑Handler postDelayed()不要让线程休眠。

于 2014-04-01T10:15:27.320 回答
1

Thread.sleep()是一种静态方法。当前线程休眠。您提供的任何线程都将被忽略。请参阅 Javadoc。

于 2014-04-01T10:15:36.560 回答
-1

创建一个任务队列,在其中存储哪个线程应该休眠,并使用可能需要定期休眠的线程检查队列的第一个元素。如果匹配线程,则弹出队列的元素并调用 sleep 方法。

于 2014-04-01T11:27:21.223 回答