Java executors:等待任务终止。

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1322147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:14:53  来源:igfitidea点击:

Java executors: wait for task termination.

javamultithreadingconcurrencyexecutorservice

提问by Raffo

I need to submit a number of task and then wait for them until all results are available. Each of them adds a Stringto a Vector(that is synchronized by default). Then I need to start a new task for each result in the Vector but I need to do this only when all the previous tasks have stopped doing their job.

我需要提交一些任务,然后等待它们,直到所有结果都可用。他们每个人都将 a 添加String到 a Vector(默认情况下是同步的)。然后我需要为 Vector 中的每个结果启动一个新任务,但只有当所有以前的任务都停止工作时,我才需要这样做。

I want to use Java Executor, in particular I tried using Executors.newFixedThreadPool(100)in order to use a fixed number of thread (I have a variable number of task that can be 10 or 500) but I'm new with executors and I don't know how to wait for task termination. This is something like a pseudocode of what my program needs to do:

我想使用 Java Executor,特别是我尝试使用Executors.newFixedThreadPool(100)以使用固定数量的线程(我有一个可变数量的任务,可以是 10 或 500)但我是执行器的新手,我不知道如何等待任务终止。这有点像我的程序需要做的伪代码:

ExecutorService e = Executors.newFixedThreadPool(100);
while(true){

/*do something*/

for(...){
<start task>
}

<wait for all task termination>

for each String in result{
<start task>
}

<wait for all task termination>
}

I can't do a e.shutdown because I'm in a while(true) and I need to reuse the executorService...

我无法执行 e.shutdown,因为我有一段时间(真实)并且我需要重用executorService...

Can you help me? Can you suggest me a guide/book about java executors?

你能帮助我吗?你能给我推荐一本关于 Java 执行器的指南/书吗?

采纳答案by oxbow_lakes

The ExecutorServicegives you a mechanism to execute multiple tasks simultaneously and get a collection of Futureobjects back (representing the asynchronous computation of the task).

ExecutorService为您提供了一种同时执行多个任务并取回Future对象集合的机制(代表任务的异步计算)。

Collection<Callable<?>> tasks = new LinkedList<Callable<?>>();
//populate tasks
for (Future<?> f : executorService.invokeAll(tasks)) { //invokeAll() blocks until ALL tasks submitted to executor complete
    f.get(); 
}

If you have Runnables instead of Callables, you can easily turn a Runnableinto a Callable<Object>using the method:

如果您有Runnables 而不是Callables,则可以使用以下方法轻松将 aRunnable转换为 a Callable<Object>

Callable<?> c = Executors.callable(runnable);

回答by Brian Agnew

When you submit to an executor service, you'll get a Futureobject back.

当您提交给执行程序服务时,您将获得一个Future对象。

Store those objects in a collection, and then call get()on each in turn. get()blocks until the underlying job completes, and so the result is that calling get()on each will complete once all underlying jobs have finished.

将这些对象存储在一个集合中,然后依次对每个对象调用get()get()阻塞直到底层作业完成,因此结果是,get()一旦所有底层作业完成,调用each 就会完成。

e.g.

例如

Collection<Future> futures = ...
for (Future f : futures) {
   Object result = f.get();
   // maybe do something with the result. This could be a
   // genericised Future<T>
}
System.out.println("Tasks completed");

Once all these have completed, then begin your second submission. Note that this might not be an optimal use of your thread pool, since it will become dormant, and then you're re-populating it. If possible try and keep it busy doing stuff.

完成所有这些后,然后开始您的第二次提交。请注意,这可能不是线程池的最佳使用方式,因为它会处于休眠状态,然后您将重新填充它。如果可能的话,试着让它忙着做事。

回答by Jonik

Can you suggest me a guide/book about java executors??

你能给我推荐一本关于 Java 执行器的指南/书吗??

I can answer this part:

我可以回答这部分:

Java Concurrency in Practiceby Brian Goetz (with Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea) is most likely your best bet.

Brian Goetz(与 Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes 和Doug Lea 合着)的Java Concurrency in Practice很可能是您最好的选择。

It's not onlyabout executors though, but instead covers java.util.concurrentpackage in general, as well as basic concurrency concepts and techniques, and some advanced topics such as the Java memory model.

不过,它不仅是关于执行程序,而是涵盖java.util.concurrent一般的包,以及基本的并发概念和技术,以及一些高级主题,如 Java 内存模型。

回答by Adamski

Rather than submitting Runnables or Callables to an Executordirectly and storing the corresponding Futurereturn values I'd recommend using a CompletionServiceimplementation to retrieve each Futurewhen it completes. This approach decouples the production of tasks from the consumption of completed tasks, allowing for example new tasks to originate on a producer thread over a period of time.

与其直接将Runnables 或Callables提交给 anExecutor并存储相应的Future返回值,我建议使用CompletionService实现Future在它完成时检索每个值。这种方法将任务的产生与已完成任务的消耗分离,例如允许在一段时间内在生产者线程上发起新任务。

Collection<Callable<Result>> workItems = ...
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletionService<Result> compService = new ExecutorCompletionService<Result>(executor);

// Add work items to Executor.
for (Callable<Result> workItem : workItems) {
  compService.submit(workItem);
}

// Consume results as they complete (this would typically occur on a different thread).
for (int i=0; i<workItems.size(); ++i) {
  Future<Result> fut = compService.take(); // Will block until a result is available.
  Result result = fut.get(); // Extract result; this will not block.
}

回答by Jarek Przygódzki

ExecutorService executor = ...
//submit tasks
executor.shutdown(); // previously submitted tasks are executed, 
                     // but no new tasks will be accepted
while(!executor.awaitTermination(1, TimeUnit.SECONDS))
    ;

There's no easy way to do what you want without creating custom ExecutorService.

如果不创建自定义 ExecutorService,就没有简单的方法可以做你想做的事。