在高层次上,以下是我打算在这里发生的事情:
- BackgroundManagerService中的BroadcastReceiver从Android接收广播(工作正常)
- BackgroundManagerService中的BroadcastReceiver将意图发送到startTestsRunnerThread()(正常工作)
- startTestsRunnerThread()创建一个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 '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");
}
}
}
答案 0 :(得分:2)
我可以看到你已经知道Thread.sleep是静态方法,并且只睡眠当前正在运行的线程有两个你正在使用sleep()的地方。
希望这有帮助。
答案 1 :(得分:1)
sleep()
是Thread
中的静态方法,即使您尝试在线程对象上调用它,也始终会休眠当前线程。这也会给你一个编译器警告:
The static method sleep(long) from the type Thread should be accessed in a static way
有没有办法将消息发送到运行BackgroundTestRunnerThread的线程并使其休眠(即,从另一个线程中调用睡眠)?
线程之间进行通信的规范方法是使用Handler
和Looper
。
此外,出于安排目的,请考虑Handler
postDelayed()
而不是暂停线程。
答案 2 :(得分:1)
Thread.sleep()
是一种静态方法。当前线程休眠。无论你提供什么线程都被忽略了。见Javadoc。
答案 3 :(得分:-1)
创建一个任务队列,您可以在其中存储应该休眠的线程以及可能需要定期休眠的线程,以检查队列的第一个元素。如果它与线程匹配,则弹出队列的元素并调用sleep方法。