我知道shutdown()
和awaitTermination()
存在。问题是池中的runnables需要能够向其添加一个未知数量(不能使用倒计时)其他runnables,如果我调用shutdown()
那些任务将被拒绝。我怎么知道它们何时完成?
答案 0 :(得分:1)
使用Future
而不是Runnable
。这种Future#isDone
方法可以帮助您。
如果您没有从Callable
返回任何有意义的内容,请使用Callable<Void>
和Future<Void>
。
答案 1 :(得分:0)
如果您能够使用Guava Futures,则可以使用Futures.allAsList
或Futures.successfulAsList
。这允许您将从Future
返回的许多ExecutorService
个实例包装到单个Future
中,然后您可以使用isDone()
检查它是否已完成(或者只是get()
,就此而言,如果你想阻止直到完成)。
答案 2 :(得分:0)
您应该使用ForkJoinTask
/ ForkJoinPool
代替将Runnable
任务提交给Executor
。 ForkJoinTask
在ForkJoinPool
内运行,可以生成任意数量的(子)任务并等待它们完成,而不会实际阻塞当前线程。当ForkJoinTask
完成所有子任务时,ForkJoinTask
就完成了,所以当初始(根)Runnable
完成时,整个计算就完成了。
有关详细信息,请参阅Oracle - The Java™ Tutorials - Fork/Join。
由于您的所有任务都是无结果的(RecursiveAction
),您应该将ForkJoinTask
(它本身是compute()
的子类)子类化。实施方法invoke(subtask)
,并通过调用invokeAll(subtask1, subtask2, ...)
,subtask.fork()
或subtask.join()
后跟MyRecursiveAction task = new MyRecursiveAction(params);
ForkJoinPool pool = new ForkJoinPool(numberOfThreads);
pool.invoke(task); // will block until task is done
来生成任意数量的新任务。
整个计算执行如下:
{{1}}
不幸的是,Fork / Join的优点有一些限制,例如:
(...)理想情况下,计算应避免同步方法或块,以及 应尽量减少其他阻止同步,除了加入 其他任务或使用广告的Phasers等同步器 配合fork / join调度。也可以进行细分任务 不执行阻塞I / O,理想情况下应该访问变量 完全独立于其他正在运行的任务访问的那些。这些 不允许检查异常,松散地强制执行准则 例如要抛出的IOExceptions。 (...)
有关详细信息,请参阅API docs of ForkJoinTask
。