//自定义线程池
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(8,16,20, TimeUnit.SECONDS,new LinkedBlockingDeque<>(20), Executors.defaultThreadFactory(), (r, executor1) -> new Thread(r).start());
System.out.println("Main 线程名称: "+Thread.currentThread().getName());
//runAsync 开启一个异步任务,接受一个Runnable,可选传入自定义线程池
CompletableFuture.runAsync(()-> System.out.println(Thread.currentThread().getName()+" CSDN——Mutou_ren CompletableFuture.runAsync"),executor);
//supplyAsync 开启一个异步任务,接受一个supplier函数,如果不指定自定义线程池默认都是使用ForkJoinPool.commonPool线程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()-> (Thread.currentThread().getName()+" CSDN——Mutou_ren CompletableFuture.supplyAsync"));
System.out.println(Thread.currentThread().getName()+" "+future1.get());
thenRun
//thenRun接受一个runnable ,无法读取前面的结果
CompletableFuture.supplyAsync(()->{
System.out.println("thenRun前置准备睡眠");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenRun前置睡眠结束");
return 1;
}).thenRun(()-> System.out.println("then run 执行,无法拿到前置任务的结果"));
thenAccept
//thenAccept可以接收一个consumer,能读取到前面的结果
CompletableFuture.supplyAsync(()->{
System.out.println("thenAccept前置准备睡眠");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenAccept前置睡眠结束");
return "thenAccept前置返回值";
}).thenAccept(e-> System.out.println("then accept 可以收到前置任务的结果为:"+e));
thenApply
//thenApply接收一个function,可以读取前面的结果并返回新的结果,
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("thenApply前置准备睡眠");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenAccept前置睡眠结束");
return "thenApply前置返回值";
}).thenApply(e->e+" then apply 添加");
System.out.println(Thread.currentThread().getName()+future2.get());
whenComplete
CompletableFuture future3 = CompletableFuture.supplyAsync(()->{
System.out.println("thenAccept前置准备睡眠");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenAccept前置睡眠结束");
return "future3";
});
//设置回调,t代表异常thrown
future3.whenComplete((e,t)-> System.out.println(Thread.currentThread().getName()+"whenComplete "+e));
thenCombine
//收集前面的和当前的CompletableFuture 的返回值作为参数,传递给function
CompletableFuture future7 = CompletableFuture.supplyAsync(()->"then").thenCombine( CompletableFuture.supplyAsync(()->"combine"),(a,b)-> a+" "+b);
System.out.println(future7.get());
thenCompose
//前面的CompletableFuture 返回值可以作为下一个CompletableFuture 的参数
CompletableFuture future8 = CompletableFuture.supplyAsync(()->"then").thenCompose(str -> CompletableFuture.supplyAsync(()-> str+" compose"));
System.out.println(future8.get());
allof
//模拟耗时操作
public static Integer getResult(int integer){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return integer;
}
List<CompletableFuture<Integer>> futureList = new ArrayList(50);
for (int i=0;i<50;i++){
futureList.add(CompletableFuture.supplyAsync(()->getResult(1),executor));
}
//在另一个流上对每个future进行join操作,等价allof
List<Integer> resultList = futureList.stream().map(e -> e.join()).collect(Collectors.toList());
System.out.println(resultList.size());
//将多个future合并成一个等待
CompletableFuture all = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
//这里返回就代表列表中所有的future全返回了
all.get();
System.out.println(futureList.stream().filter(e -> !e.isDone()).count());
anyof
List<CompletableFuture<Integer>> futureList = new ArrayList(50);
for (int i=0;i<50;i++){
futureList.add(CompletableFuture.supplyAsync(()->getResult(1),executor));
}
CompletableFuture any = CompletableFuture.anyOf(futureList.toArray(new CompletableFuture[futureList.size()]));
//这里返回就代表列表中有future返回了
any.get();
System.out.println(futureList.stream().filter(e -> !e.isDone()).count());
原理
在CompletableFuture.supplyAsync
等方法中,实际上就是新建了一个CompletableFuture
对象,然后使用线程池运行任务并立即将这个CompletableFuture
对象返回。在线程池运行任务时,会在run后将结果通过future.complete()
或异常future.completeExceptionlly()
设置到CompletableFuture
对象中
Future.get
调用get时会判断任务状态是否结束,若没有结束则构建成等待节点并park
;当任务完成进行set结果或异常set异常时,会通过finishCompletion()
将所有等待的节点线程unpark
并删除节点,思想还是AQS那套思想