我有一个需要在for循环中处理的40000条记录的列表。由于我有一个双处理器系统。我创建了一个这样的fixedThreadPool:
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
并将ArrayList
分为两个子列表。对于这些子列表中的每一个,我创建了一个执行相同功能的Callable
(涉及迭代子列表并进行一些处理)并返回Future
个对象。
我使用Callable
提交了这两个executorServiceObject.submit(callable)
,并将返回的Future
对象添加到我的Future
对象列表中
这是我的问题:
我写了System.Out.printLn("Processed Item" +item.id) // consider item as the name of reference variable for current iteration
一切都很好,我可以看到两个线程同时工作。但过了一段时间,其中一个线程已停止处理。只有一个线程在运行。 (我知道这是因为我可以在控制台上看到给予线程2的id不再被打印了。)
有谁知道这是怎么回事?我的意思是为什么ExecutorService停止运行第二个线程。
提前感谢您的帮助。
我之前应该添加示例代码:
public List<Output> processInputs(List<Input> inputs)
throws InterruptedException, ExecutionException {
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<Future<Output>> futures = new ArrayList<Future<Output>>();
for (final Input input : inputs) {
Callable<Output> callable = new Callable<Output>() {
public Output call() throws Exception {
Output output = new Output();
// process your input here and compute the output
return output;
}
};
futures.add(service.submit(callable));
}
service.shutdown();
List<Output> outputs = new ArrayList<Output>();
for (Future<Output> future : futures) {
outputs.add(future.get());
}
return outputs;
答案 0 :(得分:1)
一切都很好,我可以看到两个线程同时工作。但过了一段时间,其中一个线程已停止处理。只有一个线程在运行。 (我知道这是因为我可以在控制台上看到给予线程2的id不再被打印了。)
我怀疑你的处理线程抛出异常。 Future.get()
方法可以抛出ExecutionException
"if the computation threw an exception"。
// the following might throw an exception if the background job threw
outputs.add(future.get());
如果有一个NPE,一个IOException等等,你的&#34;处理你的输入&#34;然后代码Callable
抛出该异常并存储在Future
中,因此它可以由get()
方法抛出,但包含在ExecutionException
中。这很有用,所以正在等待的线程可以获取并处理(记录等)后台线程抛出的异常。
我不是让你的processInputs(...)
方法将异常抛给可能会丢失的调用者,而是在while
循环中执行以下操作:
try {
outputs.add(future.get());
} catch (InterruptedException ie) {
// always a good pattern if the thread that is waiting was interrupted
Thread.currentThread().interrupt();
return;
} catch (ExecutionException ee) {
// somehow log the error
logger.error("Computation failed to process", ee);
// now continue and get the next future in the list
}
如果你没有抓住并正确处理ExecutionException
,那么处理异常也会杀死调用processInputs(...)
的线程。