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

如何在Java中等待多个任务的完成?,java,multithreading,concurrency,Java,Multithreading,Concurrency,在Java应用程序中实现并发的正确方法是什么?我知道线程之类的东西,当然,我已经为Java编程10年了,但是没有太多并发性方面的经验 例如,我必须异步加载一些资源,只有在加载完所有资源后,我才能继续并做更多的工作。不用说,他们将如何结束还没有定论。我该怎么做 在JavaScript中,我喜欢使用jQuery.deferred基础结构 $.when(deferred1,deferred2,deferred3...) .done( function(){//here everything i

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

例如,我必须异步加载一些资源,只有在加载完所有资源后,我才能继续并做更多的工作。不用说,他们将如何结束还没有定论。我该怎么做

在JavaScript中,我喜欢使用
jQuery.deferred
基础结构

$.when(deferred1,deferred2,deferred3...)
 .done(
   function(){//here everything is done
    ...
   });

但是我在Java中做什么呢?

我会使用并行流

Stream.of(runnable1, runnable2, runnable3).parallel().forEach(r -> r.run());
// do something after all these are done.
如果需要异步,那么可以使用池或线程

我必须异步加载一些资源

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

List<String> urls = ....

Map<String, String> map = urls.parallelStream()
                              .collect(Collectors.toMap(u -> u, u -> download(u)));
列出URL=。。。。
Map Map=url.parallelStream()
.collect(Collectors.toMap(u->u,u->download(u));

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

您可以使用线程池和执行器来执行此操作


如果我没有使用并行流或Spring MVC的TaskExecutor,我通常使用
CountDownLatch
。用#个任务实例化,每个完成任务的线程减少一次
CountDownLatch.await()
等待,直到闩锁位于0。真的很有用


阅读更多信息:

我通常选择异步通知开始、通知进度、通知结束方法:

class Task extends Thread {
    private ThreadLauncher parent;

    public Task(ThreadLauncher parent) {
        super();
        this.parent = parent;
    }

    public void run() {
        doStuff();

        parent.notifyEnd(this);
    }

    public /*abstract*/ void doStuff() {
        // ...
    }
}


class ThreadLauncher {

    public void stuff() {
        for (int i=0; i<10; i++)
            new Task(this).start(); 
    }

    public void notifyEnd(Task who) {
        // ...
    }
}
类任务扩展线程{
私有线程启动器父级;
公共任务(ThreadLauncher父级){
超级();
this.parent=parent;
}
公开募捐{
doStuff();
父。notifyEnd(本);
}
public/*abstract*/void doStuff(){
// ...
}
}
类线程启动器{
公共物品{

对于(inti=0;i这是我使用线程的一个例子。它是一个静态executerService,固定大小为50个线程

public class ThreadPoolExecutor {

private static final ExecutorService executorService = Executors.newFixedThreadPool(50,
        new ThreadFactoryBuilder().setNameFormat("thread-%d").build());

private static ThreadPoolExecutor instance = new ThreadPoolExecutor();

public static ThreadPoolExecutor getInstance() {
    return instance;
}

public <T> Future<? extends T> queueJob(Callable<? extends T> task) {
    return executorService.submit(task);
}

public void shutdown() {
    executorService.shutdown();
}
}
公共类ThreadPoolExecutor{
私有静态最终ExecutorService ExecutorService=Executors.newFixedThreadPool(50,
新建ThreadFactoryBuilder().setNameFormat(“线程-%d”).build();
私有静态ThreadPoolExecutor实例=新ThreadPoolExecutor();
公共静态ThreadPoolExecutor getInstance(){
返回实例;
}

公共未来你可以通过多种方式实现它

1.
invokeAll()
API

执行给定的任务,当所有任务完成时,返回一个保存其状态和结果的未来列表

二,

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

CountDownLatch
使用给定的计数进行初始化。由于调用了
countDown(),等待方法会一直阻塞,直到当前计数达到零为止< /代码>方法,在此之后,所有等待线程都被释放,随后的任何调用等待立即返回。这是一次性的现象——计数不能重置。如果需要重置计数的版本,请考虑使用循环屏障。

3.或者另一种方式是
newWorkStealingPool()

查看相关SE问题:


$的行为相同。在
jQuery
中,您可以在
Java8
中使用名为
CompletableFuture
的类进行存档。该类提供了使用
Promises
的API。为了创建异步代码,您可以使用它的
静态
创建方法之一,如
\runAsync
#SupplySync
。然后使用
#应用一些结果计算,然后应用

,如果我使用Java 8或更高版本,我个人会这样做

// Retrieving instagram followers
CompletableFuture<Integer> instagramFollowers = CompletableFuture.supplyAsync(() -> {
    // getInstaFollowers(userId);

    return 0; // default value
});

// Retrieving twitter followers
CompletableFuture<Integer> twitterFollowers = CompletableFuture.supplyAsync(() -> {
    // getTwFollowers(userId);

    return 0; // default value
});

System.out.println("Calculating Total Followers...");
CompletableFuture<Integer> totalFollowers = instagramFollowers
    .thenCombine(twitterFollowers, (instaFollowers, twFollowers) -> {
         return instaFollowers + twFollowers; // can be replaced with method reference
});

System.out.println("Total followers: " + totalFollowers.get()); // blocks until both the above tasks are complete
//检索instagram关注者
CompletableFuture instagramFollowers=CompletableFuture.SupplySync(()->{
//getInstaFollowers(用户ID);
返回0;//默认值
});
//检索twitter关注者
CompletableFuture twitterFollowers=CompletableFuture.SupplySync(()->{
//getTwFollowers(userId);
返回0;//默认值
});
System.out.println(“计算追随者总数…”);
CompletableFuture totalFollowers=instagramFollowers
.thenCombine(twitterFollowers,(instaFollowers,twFollowers)->{
return instaFollowers+twFollowers;//可以替换为方法引用
});
System.out.println(“Total followers:+totalFollowers.get());//阻塞,直到上述两个任务都完成
我使用了
supplyAsync()

最后,我使用了
thenCombine()
来连接两个
CompletableFuture
。如果两个
CompletableFuture
相互依赖,您也可以使用
thenCombine()
来连接两个
CompletableFuture
。但是在这种情况下,由于两个任务都可以并行执行,我使用了
thenCombine()


方法
getInstaFollowers(userId)
getTwFollowers(userId)
都是简单的HTTP调用或其他东西。

什么版本的Java?看看谷歌上的RxJavaLook-up Java线程。在Java中很容易实现并发。@FelipeSulser很容易出错,这通常可以从SO上的问题中看出。CountdownLatch或CyclicBarrier可以help@RobinJonssonforEach在所有任务完成后才会返回已完成。不支持异步运行流代码,这就是为什么需要时需要执行其他操作的原因。您不总是具有可运行功能,也不总是可以控制异步。例如,我调用了一个名为
getMapAsync(OnMapReadyCallback)的外部方法.
它会立即返回,并启动自己的线程。还有其他事情
ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutor.getInstance();

List<Future<? extends ReturnType>> results = new LinkedList<>();

for (Type Type : typeList) {
            Future<? extends ReturnType> future = threadPoolExecutor.queueJob(
                    new MultipleExecutor(needed parameters));
            results.add(future);
        }

        for (Future<? extends ReturnType> result : results) {
            try {
                if (result.get() != null) {
                    result.get(); // here you get the return of one thread
                }
            } catch (InterruptedException | ExecutionException e) {
                logger.error(e, e);
            }
        }
// Retrieving instagram followers
CompletableFuture<Integer> instagramFollowers = CompletableFuture.supplyAsync(() -> {
    // getInstaFollowers(userId);

    return 0; // default value
});

// Retrieving twitter followers
CompletableFuture<Integer> twitterFollowers = CompletableFuture.supplyAsync(() -> {
    // getTwFollowers(userId);

    return 0; // default value
});

System.out.println("Calculating Total Followers...");
CompletableFuture<Integer> totalFollowers = instagramFollowers
    .thenCombine(twitterFollowers, (instaFollowers, twFollowers) -> {
         return instaFollowers + twFollowers; // can be replaced with method reference
});

System.out.println("Total followers: " + totalFollowers.get()); // blocks until both the above tasks are complete