如何在Java中等待完成多个任务?

f.k*_*sis 9 java concurrency multithreading

在Java应用程序中实现并发的正确方法是什么?我知道Threads和东西,当然,我已经为Java编程了10年了,但是并没有太多的并发经验.

例如,我必须异步加载一些资源,并且只有在加载完所有资源之后,我才能继续并做更多的工作.不用说,他们没有完成任务的顺序.我该怎么做呢?

在JavaScript中,我喜欢使用jQuery.deferred基础设施

$.when(deferred1,deferred2,deferred3...)
 .done(
   function(){//here everything is done
    ...
   });
Run Code Online (Sandbox Code Playgroud)

但是我在Java中做什么?

Pet*_*rey 5

我会使用并行流。

Stream.of(runnable1, runnable2, runnable3).parallel().forEach(r -> r.run());
// do something after all these are done.
Run Code Online (Sandbox Code Playgroud)

如果您需要这是异步的,那么您可以使用池或线程。

我必须异步加载一些资源,

你可以像这样收集这些资源。

List<String> urls = ....

Map<String, String> map = urls.parallelStream()
                              .collect(Collectors.toMap(u -> u, u -> download(u)));
Run Code Online (Sandbox Code Playgroud)

一旦同时下载所有资源,这将为您提供所有资源的映射。默认情况下,并发将是您拥有的 CPU 数量。


Rav*_*abu 5

您可以通过多种方式实现它.

1. ExecutorService invokeAll() API

执行给定的任务,返回完成所有状态和结果的Futures列表.

2. CountDownLatch

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助.

A CountDownLatch用给定的计数初始化.由于方法的调用,await方法阻塞直到当前计数达到零countDown(),之后释放所有等待的线程,并且任何后续的await调用立即返回.这是一次性现象 - 计数无法重置.如果您需要重置计数的版本,请考虑使用CyclicBarrier.

3. ForkJoinPoolnewWorkStealingPool()执行人是另一种方式

看看相关的SE问题:

如何等待一个产生它自己的线程的线程?

执行程序:如果递归创建任务,如何同步等待所有任务完成?


Rob*_*son 4

如果我不使用并行 Streams 或 Spring MVC 的 TaskExecutor,我通常使用CountDownLatch. 使用任务数进行实例化,为每个完成其任务的线程减少一次。CountDownLatch.await()等待直到锁存器为 0。非常有用。

在这里阅读更多内容:JavaDocs