异步CompletableFuture线程
tips:解释下主线程等待,子线程执行,如果子线程发生异常会被捕捉,主线程也会发生异常而终止,不会一直阻塞下去
ExecutorService executorService= Executors.newSingleThreadExecutor();
Future<Double> cf = executorService.submit(()->{
System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
if(false){//改成ture后就抛异常了,cf.get()也不会一直阻塞主线程
throw new RuntimeException("test");
}else{
System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
return 1.2;
}
});
System.out.println("run result->"+cf.get());
supplyAsync异步带有返回值
CompletableFuture completableFuture= CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
return "我是返回值";
});
System.out.println("completableFuture result->"+completableFuture.get());
runAsync异步没有返回值
CompletableFuture cf = CompletableFuture.runAsync(()->{
System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
if(false){
throw new RuntimeException("test");
}else{
System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
}
});
System.out.println("main thread start,time->"+System.currentTimeMillis());
//等待子任务执行完成
System.out.println("run result->"+cf.get());
CompletableFuture里面执行的其实还是Executor的实现类,默认执行的是ForkJoinPool
源码如下:
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
static Executor screenExecutor(Executor e) {
if (!useCommonPool && e == ForkJoinPool.commonPool())//这里是ForfJoinPool
return asyncPool;
if (e == null) throw new NullPointerException();
return e;
}
如果是机器是单核的,就会创建一个ThreadPerTaskExecutor的执行器:
源码如下:
private static final boolean useCommonPool =
(ForkJoinPool.getCommonPoolParallelism() > 1);//判断单核多核返回boolean值
private static final Executor asyncPool = useCommonPool ?
ForkJoinPool.commonPool()
: new ThreadPerTaskExecutor();//单核就new一个执行器
ThreadPerTaskExecutor 实现Executor接口并且创建一个单线程
static final class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) { new Thread(r).start(); }
}
基于上述源码可以看到CompletableFuture应该有两个重载Executor的方法
于是乎有如下静态构造方法:
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
/111111111111111111111111111
ForkJoinPool forkJoinPool=new ForkJoinPool();
CompletableFuture completableFuture=CompletableFuture.supplyAsync(()->{
//do yourself
return xxxxx;
},forkJoinPool);
System.out.println("completableFuture result->"+completableFuture.get());
/22222222222
ExecutorService executorService= Executors.newSingleThreadExecutor();
// 创建异步执行任务:
CompletableFuture cf = CompletableFuture.runAsync(()->{
//do yourself
},executorService);
System.out.println("main thread start,time->"+System.currentTimeMillis());
//等待子任务执行完成
System.out.println("run result->"+cf.get());
异步回调 1、thenApply:表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
2.thenApplyAsync
ForkJoinPool pool=new ForkJoinPool();
// 创建异步执行任务:
CompletableFuture cf = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread()+" 任务一,开始time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread()+" 任务一,结束time->"+System.currentTimeMillis());
return "123456789";
},pool);
Object o = cf.get();
System.out.println(o);
CompletableFuture completableFuture = cf.thenApplyAsync((result)->{
System.out.println(Thread.currentThread()+" 任务二,开始time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread()+" 任务二,结束time->"+System.currentTimeMillis());
return "456789123"+result;
});
System.out.println("main thread start cf.get(),time->"+System.currentTimeMillis());
System.out.println(completableFuture.get());
pool.shutdown();
thenAccept:接收上一个任务的执行结果作为入参,但是没有返回值 thenRun:没入参也没返回值
ForkJoinPool pool=new ForkJoinPool();
// 创建异步执行任务:
CompletableFuture cf = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "123";
},pool);
CompletableFuture completableFuture = cf.thenApply((result)->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "456";
}).thenAccept((result)->{//接收上一个任务的执行结果作为入参,但是没有返回值
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收:"+result);
}).thenRun(()->{//没入参也没返回值
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("啥也不干");
});
System.out.println(":::::::"+cf.get());
System.out.println("等待最后一个thenRun执行完成completableFuture才输出:"+completableFuture.get());

exceptionally方法指定某个任务执行异常时执行的回调方法, 会将抛出异常作为参数传递到回调方法中, 如果该任务正常执行,exceptionally 方法返回的CompletionStage的result就是该任务正常执行的结果( CompletableFuture<T> implements Future<T>, CompletionStage<T>)
ForkJoinPool pool=new ForkJoinPool();
// 创建异步执行任务:
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
System.out.println("任务一");
if(true){
throw new RuntimeException("test");
}else{
return 1.23;
}
},pool);
//cf执行异常时,将抛出的异常作为入参传递给回调方法
CompletableFuture<Double> cf2= cf.exceptionally((param)->{
System.out.println("任务二");
System.out.println("error stack trace->");
param.printStackTrace();
System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
return -1.0;
});
//cf正常执行时执行的逻辑,如果执行异常则不调用此逻辑
CompletableFuture cf3=cf.thenAccept((param)->{
System.out.println("任务三");
System.out.println("param->"+param);
});
//等待子任务执行完成,此处无论是任务二和任务三都可以实现job2退出,主线程才退出
// 如果是cf,则主线程不会等待任务二执行完成自动退出了
//cf2.get时,没有异常,但是依然有返回值,就是cf的返回值
System.out.println("》》》》》》》》》》->"+cf2.get());
等一组线程完成输出结果
package org.wangbiao.es.restclient.util;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Data
@Slf4j
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyElement {
private String name;
private Integer result;
public static void main(String[] args) {
List<MyElement> elementList = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
elementList.add(MyElement.builder().result(i).name(i + "0000000").build());
}
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < elementList.size(); i++) {
final int index = i;
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
// 这里模拟一个异步执行的任务,比如进行一些计算等,返回一个结果
int result = performTask(elementList.get(index));
elementList.get(index).setResult(result);
return null;
});
futures.add(future);
}
// 等待所有的CompletableFuture都执行完成
// CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// 输出每个元素以及对应的结果
for (MyElement element : elementList) {
System.out.println("元素: " + element.getName() + ", 结果: " + element.getResult());
}
}
private static int performTask(MyElement ele) {
// 这里可以替换为真实的、根据元素不同而执行不同逻辑的任务,这里简单返回一个和元素名称相关的数值作为示例
return ele.getResult() + 1;
}
}
本文来自博客园,作者:余生请多指教ANT,转载请注明原文链接:https://www.cnblogs.com/wangbiaohistory/p/16130391.html

浙公网安备 33010602011771号