【问题标题】:Future.get is blocking?Future.get 阻塞了?
【发布时间】:2012-10-14 00:06:47
【问题描述】:
参考以下代码。
for (Future<Long> future : list) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
现在当我调用 future.get 时,这会阻塞调用吗?因此,如果我在 Android 应用程序的主线程上执行此操作会导致 ANR 异常吗?我注意到 Interrupted 异常也被抛出,这是否意味着它们是在 get 函数中的线程上调用的睡眠?
【问题讨论】:
标签:
android
executorservice
【解决方案1】:
-
是的,Future.get() 的文档说:
如有必要,等待计算完成,然后检索其结果。
因此,它将阻塞直到计算结果可用,或计算被中断(取消或导致异常)。
如果您的计算需要很长时间才能完成,它可能会导致 ANR。
-
再次,来自Future.get()的文档:
@throws InterruptedException 如果当前线程在等待时被中断
现在,由于您从主线程调用 Future.get(),我怀疑是 Android 系统中断了您的主线程以试图使其再次响应。但这也可能是由您的应用程序的另一个线程引起的 - 很难说,因为您没有指定您的应用程序做什么,它创建什么线程,您何时使用 ExecutorService (如果是,哪个实现),等等。
不,FutureTask.get()(我相信这是您正在使用的Future 的实现)不会调用Thread.sleep()。相反,将线程置于等待模式是通过 线程停放 完成的,这会导致它在发出信号之前不会被调度执行。如果在主线程中完成,这可能会导致 ANR 错误。有关parking 机制的详细信息,请考虑阅读文档和this question
【解决方案2】:
您可以通过调用 future.isDone() 来简单地检查未来是否“完成”。代码示例:
String result = "";
if (myFuture.isDone()) result = (String) myFuture.get();
您可能希望无限循环地检查它。
【解决方案3】:
当心future.get() 的死锁。如果MainThread、调用future.get() 和WorkerThread 都是同步的(在同一个对象上),那么你会遇到死锁。