有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java sleep()线程是睡眠主线程,而不是单独指定的线程

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

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

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

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

--刚刚创建的作为BackgroundTestRunnerThread实例的线程处于休眠状态60秒(不工作)。从大量日志记录中,当“BackgroundTestRunnerThread.sleep(毫秒);”执行时,它将在主线程中运行

编辑:从答案中我意识到sleep()是一种静态方法,只在当前线程上工作。有没有一种方法可以将消息发送到运行BackgroundTestRunnerThread的线程中并使其处于睡眠状态(即,从另一个线程中调用睡眠)

我意识到,根据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 '安卓: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


共 (4) 个答案

  1. # 1 楼答案

    sleep()Thread中的一个静态方法,始终休眠当前线程,即使您试图在线程对象上调用它。这还会给您一个编译器警告:

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

    Is there a way to send a message into the thread that is running BackgroundTestRunnerThread and have it sleep (i.e., have sleep called from within the other thread)?

    线程间通信的标准方式是使用HandlerLooper

    此外,对于调度的目的,考虑^ {CD3>}{{CD6>},而不是休眠线程。

  2. # 2 楼答案

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

  3. # 3 楼答案

    Thread.sleep()是一种静态方法。当前线程处于休眠状态。不管你提供什么线索都会被忽略。请参阅Javadoc

  4. # 4 楼答案

    正如我所看到的,你们已经知道了。sleep是静态方法,只休眠当前正在运行的线程。有两个地方使用sleep()

    1. 背景TestRunnerThread。睡眠时间(睡眠时间*1000);in run()方法:这不是问题,因为它总是在BackgroundTestRunnerThread线程中调用,而不是在主线程中调用
    2. pause(int毫秒)方法:我看不到您的主线程代码,但很可能您正在从main调用pause方法,假设它将睡眠BackgroundTestRunnerThread线程,但因为它可能是从主线程调用的,所以它将使主线程睡眠而不是另一个线程

    希望这有帮助