我有这个简单的问题:
在一项服务中,我需要再运行2个以上的线程,我需要一个唤醒锁才能让它们被执行。我举个例子:
wl.aquire();
if (true) {
mExecutorService.execute(thread1);
}
if (true) {
mExecutorService.execute(thread2);
}
wl.release();
那么,在这种情况下,一旦2个线程开始或等待它们完成后唤醒锁定将被释放?
如果没有,我需要唤醒锁,以便在它们运行时保持正常运行,并且只有在最后一个线程完成时才释放它。我怎样才能做到这一点?我是否必须在线体的内部获得新的唤醒锁?
谢谢
答案 0 :(得分:4)
根据Executor execute()
文档:“在将来的某个时间执行给定的命令。该命令可以在新线程,池化线程或调用线程中执行,具体取决于执行者实施。“
所以这取决于你正在使用的具体执行程序。
我认为你应该使用submit()
给执行官一份新工作。
如果您坚持使用Executor,则get()
返回的Future上的submit()
将会阻止,直到结果可用。
所以你可以打电话:
Future<Result> result_1 = mExecutorService.execute(Runnable1);
Future<Result> result_2 = mExecutorService.execute(Runnable2);
result_1.get();
result_2.get();
或者,您可以启动两个线程并等待它们完成:
Thread t1 = new Thread(Runnable1);
Thread t2 = new Thread(Runnable2);
t1.start();
t2.start();
t1.join();
t2.join();
希望这有帮助。
答案 1 :(得分:1)
假设您从AsyncTask
或后台线程运行此代码。在调用[Thread.join()]
wl.release();
查看此link了解join()
详细信息
EDIT1:在执行程序上,您还可以使用具有长等待值的awaitTermination()来等待它完成所有任务。以下代码来自官方java doc:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
答案 2 :(得分:0)
请参阅http://developer.android.com/reference/android/os/PowerManager.WakeLock.html - 正确的方法是获取正在运行的两个线程中的唤醒锁。给出你的示例代码,你需要在thread1和thread2中有一个成员变量来存储wakelock,以及一些传递wakelock的方法,也许是这样的:
thread1.setWakelock(wl);
thread2.setWakelock(wl);
class Thread implements Runnable {
PowerManager.Wakelock mWakelock;
void setWakelock(PowerManager.Wakelock wl) {
mWakelock = wl;
}
}
然后在thread1和thread2中,你需要:
run() {
mWakelock.acquire();
... your existing code here ...
mWakelock.release();
}
请注意,这将起作用,因为默认情况下唤醒锁被引用计数;请参阅PowerManager.WakeLock.setReferenceCounted()。
等待线程完成使用thread.join()是错误的;它会阻止UI线程,你会得到一个ANR,就像你发现的那样。