26、java8 CompletableFuture 异步任务用法
异步大概的意思是,在编程过程中,大家各走各的路,不需要互相干扰 —>你走你的阳关道,我过我的独木桥
在使用线程池时,只有submit提交的时候,返回的是一个callable,带返回结果的一个future
/** 1、线程池的创建
* 1)、newFixedThreadPool 一个定长的线程池,可以控制线程池线程的个数,超出的线程会在队列中等待
* 2)、newCachedThreadPool 创建一个可缓存的线程池,超出的线程可以回收,没有的话,可以新建一个线程
* 3)、newScheduledThreadPool 创建一个定时,周期行的的线程池,可以定时周期性的执行,线程
* 3)、newSingleThreadScheduledExecutor 创建一个单线程化的的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
*
* 2、ExecutorService 提交的方法,
* executor(Runnable)
* submit(Runnable/cllable)
* invokeAny(callable 集合) 返回任一个task的结果
* invokeAll(callable 集合) 返回所有的task的结果
*/
之前操作是:创建一个线程池–>在对单个的线程进行一系列的操作–>最后关闭这些资源
重点:一个completetableFuture就代表了一个任务。他能用Future的方法。还能做一些之前说的executorService配合futures做不了的。
相比较于上述的好处:之前future需要等待isDone为true才能知道任务跑完了。或者就是用get方法调用的时候会出现阻塞。而使用completableFuture的使用就可以用then,when等等操作来防止以上的阻塞和轮询isDone的现象出现。
1、常用的两个方法:
supplyAsync :创建存在返回值的异步任务 callable 相当于创建一个线程池中submit中的参数是callable
runAsync:创建没有返回值的异步任务 runnable 相当于创建一个线程池中submit中的参数是runnable
注意点: 这两方法各有一个重载版本,可以指定执行异步任务的Executor实现,如果不指定,默认使用ForkJoinPool.commonPool(),如果机器是单核的,则默认使用ThreadPerTaskExecutor,该类是一个内部类,每次执行execute都会创建一个新线程。
相当于,每次执行一个任务,就创建了一个线程
package com.example.ThreadStudy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
* CompleteTableFuture:异步任务使用
*
* @author LZH
* @version 1.0
* @date 2022/04/11 16:07:24
*/
public class CompleteTableFutureDemo {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
/**
* supplyAsync 存在返回值 callable
*/
CompletableFuture<List<String>> demo1 = CompletableFuture.supplyAsync(()->{
List<String> a = new ArrayList<>();
a.add("11");
return a;
}, executor);
/**
* runAsync 没有返回值 runnable
*/
CompletableFuture demo2 = CompletableFuture.runAsync(()->{
},executor);
}
2、回调函数
thenAccept :和 thenApply一样,但是没有返回值
thenAcceptAsync :和 thenApplyAsync ,指定线程池,且没有返回值
thenApply 表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
thenApplyAsync :表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
区别:thenApply 是在异步任务执行完成后,重新启动了一个线程来执行回调函数中的方法, 使用的是默认的 ForkJoinPool.commonPool() 线程池
thenApplyAsync 是在异步任务执行完成后,继续使用之前的那个线程继续执行回调函数,指定线程池
3、最后调用 allOf / anyOf(一定要调用的)
allOf返回的CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。join表示加阻塞,防止子线程没有跑完
例子
CompletableFuture.allOf(voidCompletableFuture3,voidCompletableFuture4,voidCompletableFuture1,yyyy,zcjb,voidCompletableFuture5,voidCompletableFuture6
,voidCompletableFuture7,voidCompletableFuture2,voidCompletableFuture).join();