【异步 CompletableFuture】

线程池

初始化线程的四种方法


1.继承Thread
Thread01 thread = new Thread01();
thread.start();

2.实现runnable接口
Runable01 runable = new Runable01();
Thread thread = new Thread(runable);
thread.start();


3.实现Callable接口+FutureTask
Callable01 callable = new Callable01();
FutureTask<Integer> futureTask = new FuntureTask<>(callable);
// get方法是阻塞等待
futureTask.get();//等待整个线程运行完成,获取返回的结果

4.线程池
// 两种创建线程池的方法
Executors
new ThreadPoolExecutor

// 七大参数
corePoolSize:核心线程数;线程池创建好以后,就准备就绪的线程,即使没有任务,也会存活;(也可以设置允许核心线程超时会后的属性allowCorethreadTimeOut)
maximumPoolSize:最大线程数量;控制资源(核心线程数量+临时线程数量)
keepAliveTime:存活时间,针对临时线程,空闲并超时,就会被回收
unit:时间单位
workQueue:阻塞队列,将多出的任务放入队列等待
threadFactory:线程的创建工厂(可以自定义)
handler:如果队列满了,按照指定的拒绝策略,拒绝任务

// 工作顺序:
1.线程池创建,准备好core数量的核心线程,准备接收任务
2.如果核心线程满了,就会将任务放入阻塞队列
3.如果阻塞队列也满了,就会创建临时线程执行任务,数量是maximumPoolSize - corePoolSize
4.临时线程数量到上限后,就要使用handler拒绝策略,拒绝任务

// 拒绝策略
1.DiscardOldestPolicy:丢弃队列中最老的任务
2.AbortPolicy:直接调用run方法运行(同步调用)
3.CallerRunsPolicy:丢弃任务,抛出异常
4.DiscardPolicy:丢弃任务

// 常见线程池
// 创建一个定长的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
// 创建缓存线程池,没有核心线程,有任务就创建临时线程
ExecutorService service = Executors.newCachedThreadPool();
// 创建任务调度的线程池,做定时任务的线程池
ExecutorService service = Executors.newScheduledThreadPool();
// 创建单一核心线程的线程池,只有一个核心线程,相当于后台使用单线程的方式执行任务
ExecutorService service = Executors.newSingleThreadExecutor();

// 给线程池提交任务,有返回值
submit();
// 给线程池提交任务,无返回值
execute();

//每次系统最好只有一两个线程池(核心业务和非核心),异步任务直接提交给线程池

线程池性能稳定,也可以获取执行结果,并捕获异常。但是在业务复杂情况下,一个异步调用可能会依赖顶一个异步调用的结果,可以使用CompletableFuture

CompletableFuture 异步编排

CompletableFuture 的创建方法


// 创建无返回值的异步任务,可以执行线程池
static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)

// 创建有返回值的异步任务,可以执行线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Runnable runnable,Executor executor)

// 测试代码,创建没有返回值的异步任务
CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);

// 测试代码,创建有返回值的异步任务
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);
future.get();

CompletableFuture 计算完成时回调方法


// 上一个任务完成,采用同一个线程完成当前任务
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
// 上一个任务完成,采用异步方式完成当前任务
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)

// 上一个任务完成,采用异步方式完成当前任务,并且指定线程池
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action,Executor executor)
// 对上一个任务出现的异常做处理
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)

// whenComplete 可以处理正常和异常的计算结果
// exceptionally 专门处理异常结果
// whenComplete 是线程执行完上一个任务后,紧接着使用这个线程执行当前任务
// whenCompleteAsync 是行完上一个任务后,随机一个线程执行当前任务

// 方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行,随机的)

// 测试代码
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
	int i = 10/0;
	System.out.println(Thread.currentThread().getId());
},executor).whenComplete((result,excption)->{
	System.out.println("上一个任务的运行结果是:"+result);
	// 虽然能得到异常信息,但是无法修改返回数据,只是监听异常
	System.out.println("上一个任务出现的异常是:"+excption);
}).exceptionally(throwable->{
	// 感知异常,同时可以对异常情况做处理
	return 10;
});

handle 方法,方法执行完成后的处理,无论成功或者失败


// 
public <U> ComletionStage<U> handle(BiFunction<? super T,? extends U> fn);
// 
public <U> ComletionStage<U> handleAsync(BiFunction<? super T,? extends U> fn);
// 
public <U> ComletionStage<U> handleAsync(BiFunction<? super T,? extends U> fn, Executor executor);

// 测试代码
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
	int i = 10/0;
	System.out.println(Thread.currentThread().getId());
},executor).handle((result,excption)->{
	if(result!=null){
		return result*2;
	}
	if(excption!=null){
		return 0;
	}
	return 0;
});

// 和complete一样,可对结果做最后的处理(可处理异常),可改变返回值

线程串行化方法


// thenApply方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值
public <U> ComletableFuture<U> thenApply(Function<? super T, ? extends U> fn)
public <U> ComletableFuture<U> thenApplyAsync(Function<? super T, ? extends U> fn)
public <U> ComletableFuture<U> thenApplyAsync(Function<? super T, ? extends U> fn, Executor executor)

// thenAccpt方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果
public ComletableStage<Void> thenAccept(Consumer<? super T> action);
public ComletableStage<Void> thenAcceptAsync(Consumer<? super T> action);
public ComletableStage<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor);

// thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完成任务后,执行thenRun的后续操作
public ComletionStage<Void> thenRun(Runnable action)
public ComletionStage<Void> thenRunAsync(Runnable action)
public ComletionStage<Void> thenRunAsync(Runnable actionn, Executor executor)

// 带有Async默认是异步执行的

线程串行化
1、thenRun:不能获取到上一步的执行结果,无返回值


.thenRunAsync(()->{
	System.out.println("任务2启动...");
}, executor);

2、thenAcceptAsync:能接收上一步结果,但是无返回值


.thenAcceptAsync((result)->{
	System.out.println("任务2启动..."+result);
}, executor);

3、thenApplyAsync:能接收上一步结果,有返回值


.thenApplyAsync((result)->{
	System.out.println("任务2启动..."+result);
	return result+" hello";
}, executor);

两个任务组合 – 都要完成


// runAfterBoth:组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务
public ComletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public ComletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public ComletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,  Executor executor);

// thenAcceptBoth:组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值
public <U> ComletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
public <U> ComletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
public <U> ComletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor);


// thenCombine:组合两个future,获取两个future的返回结果,并返回当前任务的返回值
public <U,V> ComletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn);
public <U,V> ComletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn);
public <U,V> ComletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn, Executor executor);

// 测试代码
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);

CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);

future01.runAfterBothAsync(future02,()->{
	System.out.println("任务3,任务1和2执行完成后,执行任务3");
},executor);

future01.thenAcceptBothAsync(future02,(f1, f2)->{
	System.out.println("任务3,任务1和2执行完成后,执行任务3");
},executor);

CompletableFuture<Integer> future03 = future01.thenCombineAsync(future02,(f1, f2)->{
	System.out.println("任务3,任务1和2执行完成后,执行任务3");
	return "3";
},executor);

两个任务组合 – 任意一个完成


// runAfterEither:组合两个任务只要有一个完成,不需要获取future的结果,处理任务,也没有返回值
public ComletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public ComletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public ComletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,  Executor executor);

// acceptEither:组合两个任务只要有一个完成,获取他的返回值,处理任务,没有返回值
public ComletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
public ComletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action);
public ComletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor);


// applyToEither:组合两个任务只要有一个完成,获取他的返回值,处理任务,有返回值
public <U> ComletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
public <U> ComletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn);
public <U> ComletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor);

// 测试代码
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);

CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread().getId());
},executor);

future01.runAfterEitherAsync(future02,()->{
	System.out.println("任务3,任务1和2任意一个完成后,执行任务3");
},executor);

future01.acceptEitherAsync(future02,(res)->{
	System.out.println("任务3,任务1和2任意一个完成后,执行任务3");
},executor);

CompletableFuture<Integer> future03 = future01.applyToEitherAsync(future02,(res)->{
	System.out.println("任务3,任务1和2任意一个完成后,执行任务3");
	return "3";
},executor);

// 两个任务,只要有一个完成,就执行任务3
// runAfterEitherAsync 不感知结果,自己没有返回值
// acceptEitherAsync 感知结果,自己没有返回值
// applyToEitherAsync 感知结果,自己有返回值

多任务组合


// allOf:等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);

// anyOf:只要有一个任务完成
public static CompletableFuture<Object> allOf(CompletableFuture<?>... cfs);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值