0

例如,我正在创建 15 个可调用任务并提交它们:

List<Future<MyResult>> futures = new ArrayList<Future<MyResult>>();
List<MyResult> myResults = new ArrayList<MyResult>();

for(int i = 1; i <= 15; i++){
    Callable<MyResult> task = new MyProcessor(//parameters);
    Future<MyResult> future = executorService.submit(task);
    futures.add(future);//used to iterate over to call get() to collect results in next for loop
}

然后我收集 15 个 MyResult 对象:

for(Future<MyResult> future : futures){
  try {
    MyResult myResult = future.get();
    processorResults.add(myResult);
    } catch (InterruptedException e) {
      //...
    } catch (ExecutionException e) {
      //...
    }
}

问题是:我有时会得到少于 15 个对象,而不是从 get() 方法中获取所有 15 个 MyResult 对象。有时 12 有时 10 有时甚至更少,有时全部 15。

我的印象是get()方法是一个阻塞调用,将等待所有 15 个线程返回各自的结果,但看起来我错过了其中的一些并继续前进。我做错了什么?我没有正确收集结果/等待结果吗?当任何 MyProcessor 任务抛出 ERROR 时会发生这种情况吗?

4

1 回答 1

6

这可能意味着您的某些工作引发了异常。很难从您的代码中分辨出来,但ExecutionException除了捕获和忽略它之外,您还需要做一些事情。

Future.get()throwsExecutionExceptionCallable您提交的RuntimeExceptioncall()方法中抛出一个。MyResult只有当方法正常返回时,它才会返回您的return. 您可以通过执行以下操作获取引发的异常:

} catch (ExecutionException e) {
    // account for the throw here, the original exception is in e.getCause()
    // log it, count it, or ...
    logger.error("Job threw exception: " + e.getCause());
}

我的印象是 get() 方法是一个阻塞调用,将等待所有 15 个线程返回各自的结果,

这是对的。当您调用它时future.get(),它将阻塞,直到作业完成 - 通过抛出异常或返回。如果正在运行的线程get()被中断,那么get()抛出一个InterruptedException也应该被捕获而不是被忽略的线程。

于 2012-07-30T17:42:10.020 回答