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