2

我有一个简单的问题:

在一项服务中,我需要再运行 2 个彼此独立的线程,并且我需要一个唤醒锁来让它们被执行。我给你举个例子:

   wl.aquire();

    if (true) {
        mExecutorService.execute(thread1);
    }

    if (true) {
        mExecutorService.execute(thread2);
    }
   wl.release();

那么,在这种情况下,唤醒锁将在 2 个线程启动后释放还是等待它们完成?

如果没有,我需要唤醒锁在它们运行时保持不变,并且只有在最后一个线程完成时才释放它。我怎样才能做到这一点?我是否必须在线程体内获取新的唤醒锁?

谢谢

4

3 回答 3

4

根据Executorexecute()文档:“在未来某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由 Executor 实现自行决定。”

所以这取决于你使用的是哪个具体的 Executor。

我认为你应该用来submit()给执行者一份新工作。

如果你坚持使用 Executor,调用get()返回的 Futuresubmit()将阻塞,直到结果可用。

所以你可以打电话:

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();

希望这可以帮助。

于 2012-11-12T14:48:25.463 回答
1

假设您正在从AsyncTask后台线程或后台线程运行此代码。您可以[Thread.join()]在调用之前调用所有线程wl.release();

查看此链接了解join()详细信息

EDIT1:在执行器上,您还可以使用具有长等待值的awaitTermination()来等待它完成所有任务。以下代码来自官方java 文档

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();
   }
 }
于 2012-11-12T14:33:51.740 回答
0

请参阅http://developer.android.com/reference/android/os/PowerManager.WakeLock.html - 正确的方法是在您正在运行的两个线程中获取唤醒锁。给定您的示例代码,您需要在 thread1 和 thread2 中使用一个成员变量来存储唤醒锁,以及传递唤醒锁的某种方式,可能像这样:

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。

于 2013-07-10T23:28:30.210 回答