【问题标题】: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】:
    1. 是的,Future.get() 的文档说:

      如有必要,等待计算完成,然后检索其结果。

      因此,它将阻塞直到计算结果可用,或计算被中断(取消或导致异常)。

    2. 如果您的计算需要很长时间才能完成,它可能会导致 ANR。

    3. 再次,来自Future.get()的文档:

      @throws InterruptedException 如果当前线程在等待时被中断

      现在,由于您从主线程调用 Future.get(),我怀疑是 Android 系统中断了您的主线程以试图使其再次响应。但这也可能是由您的应用程序的另一个线程引起的 - 很难说,因为您没有指定您的应用程序做什么,它创建什么线程,您何时使用 ExecutorService (如果是,哪个实现),等等。

    4. 不,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 都是同步的(在同一个对象上),那么你会遇到死锁。

        【讨论】:

          猜你喜欢
          • 2020-11-07
          • 1970-01-01
          • 1970-01-01
          • 2017-07-23
          • 1970-01-01
          • 1970-01-01
          • 2012-02-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多