java - sleep() 线程正在 hibernate 主线程,而不是单独的指定线程

标签 java android multithreading android-anr-dialog

从较高的层面来看,我打算在这里实现以下目标:

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

--BackgroundManagerService 中的 BroadcastReceiver 发送 Intent 到 startTestsRunnerThread()(工作正常)

-- startTestsRunnerThread() 创建一个BackgroundTestRunnerThread并启动它(看起来工作正常)

-- 作为BackgroundTestRunnerThread 实例且刚刚创建的线程将 hibernate 60 秒(不起作用)。从广泛的日志记录来看,当“BackgroundTestRunnerThread.sleep(毫秒);”时被执行,它正在主线程中运行。

编辑:我从答案中意识到 sleep() 是一个静态方法,仅适用于当前线程。有没有办法将消息发送到正在运行的BackgroundTestRunnerThread线程中并使其 hibernate (即从另一个线程内调用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");
    }
  }
}

enter image description here

最佳答案

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

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

希望这有帮助。

关于java - sleep() 线程正在 hibernate 主线程,而不是单独的指定线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22782836/

相关文章:

multithreading - 如何使用 Spring Framework 调用 Runnable?

python - 如何使用pyserial清除热插拔缓冲区中的先前数据

java - Eclipse JDK 7启动失败

java - 通用方法使用未知对象类型java

php - 必填字段缺少 json/android

android - 如何让 textView 准确地包裹它的多行内容?

java - 获取出现在 ListView 外部的 edittext 值,获取 OnItemClick 内部的 edittext 值

java - 二维数组中两点之间的计算

java - 在java中使用线程不安全的java.sql.Connection对象有什么可能性?

c# - Parallel.ForEach 中的异常堆栈跟踪和聚合