一、知识点
1、线程池
线程池可以使用系统已有的线程池,也可以自己创建一个
1. 线程池7大参数
corePoolSize:核心线程数大小
maximumPoolSize:最大线程数
long keepAliveTime:非核心线程存活时间
TimeUnit unit:时间单位
BlockingQueue workQueue:阻塞队列
ThreadFactory threadFactory:线程创建工厂
RejectedExecutionHandler handler:拒绝策略
拒绝策略:
主要看juc包下的拒绝策略,juc包下系统提供的拒绝策略有4种:
AbortPolicy:抛弃任务,并抛出异常
CallerRunsPolicy:不进行异步执行,由任务的当前方法直接执行
DiscardOldestPolicy:抛弃最老的任务
DiscardPolicy:抛弃任务,不跑出异常
2、工作顺序
1、创建线程池,线程池准备核心线程,准备接收任务
2、如果核心线程满了,则将任务放到阻塞队列中
3、如果阻塞队列满了,则开启新线程,知道到达最大线程数
4、如果已经到达最大线程数据,则根据拒绝策略处理线程
举例:
创建了一个core:13,maxiMumPoolSize:20,workQueue:50的线程池,那么100个任务进来,处理顺序如下:
首先核心线程先获取13个任务,然后50个任务进入阻塞队列,再开7个非核心线程,剩下30个任务根据拒绝策略进行处理
3、系统提供的默认线程池
- Exectors.newCachedThreadPool():核心线程数是0,代表所有线程都会被回收
- Exectors.newFixedThreadPool():核心线程数=最大线程数,所有线程都不会被回收
- Exectors.newScheduledThreadPool():可以设置任务多久之后执行,用来做定时任务
- Exectors.newSingledThreadExectors()
为什么要使用线程池
1、降低损耗,通过重复利用已经创建好的线程,来降低创建和销毁线程的损耗
2、提高响应速度,当线程池中的线程数没有达到最大线程数时,有的线程处于等待任务的状态,因此有任务进来,能够立马被响应
3、利于管理线程,有助于管理线程的创建和销毁
2、线程异步编排
CompletableFuture
1. 创建异步对象
CompletableFuture由四种方法来执行异步任务
1. static void CompletableFuture.runAsync(Runnable runnable);
执行一个异步任务,不指定线程池,没有返回对象
2. static void CompletableFuture.runAsync(Runnable runnable,Exector exector);
执行一个异步任务,指定线程池,没有返回对象
3. static CompletableFuture.supplyAsync(Supplier supplier);
执行一个异步任务,不指定线程池,有返回对象
4. static CompletableFuture.supplyAsync(Supplier supplier,Exector exector);
执行一个异步任务,指定线程池,有返回对象
案例
ExectorService exector = Exectors.newFixedThreadPool();
CompletableFuture.runAsync(()->{
//异步任务
});
CompletableFuture.runAsync(()->{
//异步任务
},exector);
CompletableFuture<T> future = CompletableFuture.supplyAsync(()->{
//异步任务
return T
});
CompletableFuture<T> future = CompletableFuture.supplyAsync(()->{
//异步任务
return T;
},exector);
//通过future.get()获取返回结果
future.get()
2. 计算完成时回调方法
1.方法完成后的感知(无法处理返回结果)
1、public CompletableFuture whenComplete(BiConsumer<? supplier T,? supplier Throwable> action);
当任务完成时,利用该任务的线程执行action任务
2、public CompletableFuture whenCompleteAsync(BiConsumer<? supplier T,? supplier Throwable> action);
当任务完成时,重新开一个线程执行action任务
3、public CompletableFuture whenCompleteAsync(BiConsumer<? supplier T,? supplier Throwable> action,Exector exector);
当任务完成时,在指定线程池中重新开一个线程执行action任务
4、public CompletableFuture exceptionally(Function<Throwable,? extends T> fn);
如果任务出现异常,则使用fn函数处理
案例
future.whenComplete((res,exection)->{
//res是返回的结果,exection是异常
});
future.whenCompleteAsync((res,exection)->{
//res是返回的结果,exection是异常
});
future.whenCompleteAsync((res,exection,exector)->{
//res是返回的结果,exection是异常,使用exector中的线程执行任务
});
future.execptionally(throwable -> {
//感知异常,同时返回默认值
return ...);
});
2.方法完成后的处理
1、public CompletionStage handle(BiFunction<? supper T,Throwable,? extends U> fn);
对返回结果进行处理,可捕获异常,使用当前任务的线程
2、public CompletionStage handleAsync(BiFunction<? supper T,Throwable,? extends U> fn);
对返回结果进行处理,可捕获异常,新开一个线程处理
3、public CompletionStage handleAsync(BiFunction<? supper T,Throwable,? extends U> fn,Exector exector);
对返回结果进行处理,可捕获异常,使用线程池中的线程处理
案例
future.handle((res,thr)->{
//res是返回结果,thr是异常
})
//另外两个类似
3. 线程串行化
1、thenRun
任务完成之后,继续执行action,不感应返回结果,async表示开启异步线程
2、thenAccept
任务完成之后,action能够感知结果,然后执行action
3、thenApply
任务完成之后,action能够感知结果,执行action,并返回结果
其他方法见api(多任务组合)
CompletableFutureAPI