我是并发新手,我试图为do-while循环实现执行器服务并发。但我总是遇到RejectedExecutionException
以下是我的示例代码:
do {
Future<Void> future = executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
// action
return null;
}
});
futures.add(future);
executor.shutdown();
for (Future<Void> future : futures) {
try {
future.get();
}
catch (InterruptedException e) {
throw new IOException(e)
}
}
}
while (true);
但这似乎不正确。我想我在错误的地方叫停机。任何人都可以帮我正确实现Executor Service in a do-while
循环。感谢。
答案 0 :(得分:3)
ExecutorService.shutdown()阻止ExecutorService
接受更多工作。当你完成提交工作时应该调用它。
同样Future.get()是一种阻塞方法,这意味着它将阻止当前线程的执行,并且循环的下一次迭代将不会继续,除非将来(在其上调用get)返回。这将在每次迭代中发生,这使得代码不平行。
您可以使用CountDownLatch等待所有作业返回。
以下是正确的代码。
final List<Object> results = Collections.synchronizedList(new ArrayList<Object>());
final CountDownLatch latch = new CountDownLatch(10);//suppose you'll have 10 futures
do {
Future<Void> future = executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
// action
latch.countDown();//decrease the latch count
results.add(result); // some result
return null;
}
});
futures.add(future);
} while (true);
executor.shutdown();
latch.await(); //This will block till latch.countDown() has been called 10 times.
//Now results has all the outputs, do what you want with them.
此外,如果您正在使用Java 8,那么您可以查看此答案https://stackoverflow.com/a/36261808/5343269
答案 1 :(得分:1)
您是对的,shutdown
方法未在正确的时间被调用。调用ExecutorService
后,shutdown
将不接受任务(除非您实现自己的版本)。
在您已经将所有任务提交给执行者之后,您应该致电shutdown
,所以在这种情况下,在do-while
循环之后的某个地方。
答案 2 :(得分:0)
来自ThreadPoolExecutor文档:
拒绝的任务
当Executor关闭时,以及当Executor对最大线程和工作队列容量使用有限边界并且已经饱和时,将拒绝方法execute(Runnable)中提交的新任务。
在任何一种情况下,execute方法都会调用RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)
method of its RejectedExecutionHandler
从您的代码中可以清楚地看到您先调用shutdown()
并稍后提交任务。
另请注意,请参阅此相关的SE问题,了解关闭ExecutorService
的正确方法:
ExecutorService's shutdown() doesn't wait until all threads will be finished