SpringBoot使⽤线程池(ThreadPoolExecutor()和Completa。。。
上⼀篇⽂章已经写到了实现线程的⼏种⽅式:
⼀、说说为什么要⽤到线程池
在处理⾼并发的时候,往往会考虑到使⽤多线程的⽅式来提⾼速率,
但是我们常见的
Thread01 extends Thread
Runable01 implements Runnable
Callable01 implements Callable
这三种⽅式是不建议直接使⽤的,具体是为什么呢?我举个列⼦⼤家应该就会懂了。
⽐如说⼀个公司技术开发⼈员有10个⼈,为了提⾼效率,每次有⼀个新的需求就会去招聘⼀个开发⼈员,这样是提⾼了很⼤的开发效率,但是随之⽽来的⼀个问题就是随着需求的完成,公司的开发⼈员会越来越多,但是需求已经做完了,那么这些开发⼈员就会没什么事⼲,导致了公司的运营成本越来越⼤,
最后导致公司破产。回到我们代码当中也是⼀样的,每创建⼀个线程就会消耗⼀定的资源,你每个请求都创建很多线程,cpu资源是有限的,最后就会导致cpu100%⽽使得整个服务器奔溃。
⽽采⽤线程池的优点如下:
- 降低资源消耗。可以重复利⽤已经创建好的线程,降低线程的创建和销毁带来的损耗。
- 提⾼响应速度。因为线程池中的线程都处于等待分配任务状态,当任务过来时可以直接执⾏。
- 提⾼线程的可管理性。如果是单cpu的话,创建多个线程,会导致资源耗尽,但是线程池有拒绝策略;另外还可以核⼼业务和⾮核⼼业务两种线程池,如果某个时间内存压⼒⼤,可以释放掉⾮核⼼业务线程池。使⽤线程池就可以使线程的管理⽅便。
⼆、使⽤Executors创建线程池
使⽤Executors创建线程池其实底层还是使⽤的ThreadPoolExecutor来创建的线程池。
1.Executor的UML图:(常⽤的⼏个接⼝和⼦类)
Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
2.线程池七⼤参数
int corePoolSize:核⼼线程数,线程池创建好就已经准备就绪的线程数量,等待接收异步任务,异步任务进来后,⾃动执⾏。核⼼线程会⼀直存在,除⾮设置了allowCoreThreadTimeOut,才允许核⼼线程超时。
int maximumPoolSize:线程池允许存在的最⼤线程数
long keepAliveTime:超时时间。如果当前线程数量⼤于核⼼数量,且在keepAliveTime时间内保持空闲,就释放掉。释放的是最⼤线程数-核⼼线程数TimeUnit unit:超时时间单位
BlockingQueue workQueue:阻塞队列,如果线程有很多,就会把线程保存在队列⾥只要线程有空闲,就去阻塞队列中取。
分类见下⽂。
ThreadFactory threadFactory:线程的创建⼯⼚
RejectedExecutionHandler handler:拒绝策略,如果线程满了采取的策略
拒绝策略分类:
①:DiscardOldestPolicy 抛弃掉最早进⼊的线程
②:DiscardPolicy 抛弃掉最新的线程
③:DiscardPolicy 剩余的线程调⽤run⽅法,变为同步执⾏
④:DiscardPolicy 抛弃掉最新的线程,并抛出异常
三、使⽤Executors创建线程池
//线程池,每个系统应该有⼀个共有的有⼀个或者是有两个
public static ExecutorService executor = wFixedThreadPool(10);
Executors创建线程池的四种⽅式:
newCachedThreadPool创建⼀个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若⽆可回收,则新建线程。
newFixedThreadPool 创建⼀个定长线程池,可控制线程最⼤并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建⼀个定长线程池,⽀持定时及周期性任务执⾏。
newSingleThreadExecutor 创建⼀个单线程化的线程池,它只会⽤唯⼀的⼯作线程来执⾏任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执⾏。
四、CompletableFuture介绍
CompletableFuture是JDK1.8版本新引⼊的类。CompletableFuture类实现了CompletionStage和Future接⼝。
具体的使⽤⽅式直接看代码:
单异步任务
/**
* ⽆返回值的异步任务 runAsync()
*/
CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
System.out.println("当前线程:"+ Thread.currentThread().getId());
int i =10/2;
System.out.println("运⾏结果:"+ i);
}, executor);
/**
* ⽅法完成后的处理
* 有返回值,但是不能修改数据
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
System.out.println("当前线程:"+ Thread.currentThread().getId());
int i =10/0;
System.out.println("运⾏结果:"+ i);
return i;
}, executor).whenComplete((res,exception)->{
//虽然能得到异常信息,但是没法修改返回数据
System.out.println("异步任务成功完成了...结果是:"+ res +"异常是:"+ exception);
}).exceptionally(throwable ->{
//可以感知异常,同时返回默认值
return10;
});
/**
* ⽅法执⾏完后端处理
* 有返回值,并且能感知异常并且修改数据
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
System.out.println("当前线程:"+ Thread.currentThread().getId());
int i =10/2;
System.out.println("运⾏结果:"+ i);
return i;
}, executor).handle((result,thr)->{
if(result != null){
return result *2;
}
if(thr != null){
System.out.println("异步任务成功完成了...结果是:"+ result +"异常是:"+ thr);
return0;
}
return0;
});
线程串⾏化
线程串⾏化
1、thenRunL:不能获取上⼀步的执⾏结果
2、thenAcceptAsync:能接受上⼀步结果,但是⽆返回值
3、thenApplyAsync:能接受上⼀步结果,有返回值
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
System.out.println("当前线程:"+ Thread.currentThread().getId());
int i =10/2;
System.out.println("运⾏结果:"+ i);
return i;
}, executor).thenApplyAsync(res ->{
System.out.println("任务2启动了..."+ res);
return"Hello"+ res;
}, executor);
System.out.println("nd....."+ ());
/
**
* 两个都完成
* 两个都完成
*/
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(()->{
System.out.println("任务⼀启动线程:"+ Thread.currentThread().getId());
int i =10/4;
System.out.println("任务⼀结束:"+ i);
return i;
}, executor);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(()->{
System.out.println("任务⼆启动线程:"+ Thread.currentThread().getId());
System.out.println("任务⼆结束:");
return"hello";
}, executor);
future01.thenAcceptBothAsync(future02,(f1,f2)->{
System.out.println("得到的结果"+f1+"_>>>>>>>>"+f2);
},executor);
CompletableFuture<String> future = future01.thenCombineAsync(future02,(f1, f2)->{ return f1 + f2+"哈哈哈";
}, executor);
/**
* 线程串⾏化
* 1、thenRunL:不能获取上⼀步的执⾏结果
* 2、thenAcceptAsync:能接受上⼀步结果,但是⽆返回值
* 3、thenApplyAsync:能接受上⼀步结果,有返回值
*
*/
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运⾏结果:" + i);
//            return i;
//        }, executor).thenApplyAsync(res -> {
/
/            System.out.println("任务2启动了..." + res);
//            return "Hello" + res;
//        }, executor);
//        System.out.println("nd....." + ());
/**
* 两个都完成
*/
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(()->{
System.out.println("任务⼀启动线程:"+ Thread.currentThread().getId());
int i =10/4;
System.out.println("任务⼀结束:"+ i);
return i;
}, executor);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(()->{
System.out.println("任务⼆启动线程:"+ Thread.currentThread().getId());
System.out.println("任务⼆结束:");
return"hello";
}, executor);
//        future01.thenAcceptBothAsync(future02,(f1,f2) ->{
//            System.out.println("得到的结果"+f1+"_>>>>>>>>"+f2);
//        },executor);
//        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> { //            return f1 + f2+"哈哈哈";
//        }, executor);
java线程池创建的四种
/**
* 两个任务只要有⼀个完成我们就执⾏任务三
* runAfterEitherAsync :不感知结果⾃⼰也⽆返回值
*/
future01.runAfterEitherAsync(future02,()->{
System.out.println("得到的结果+");
},executor);
/**
* 两个任务只要有⼀个完成我们就执⾏任务三
* acceptEitherAsync :可以感知结果⾃⼰也⽆返回值
*/
future01.acceptEitherAsync(future02,(res)->{
System.out.println(res);
},executor);
/**
* 两个任务只要有⼀个完成我们就执⾏任务三
* applyToEitherAsync :可以感知结果也有返回值
*/
future01.applyToEitherAsync(future02,(res)->{
String();
},executor);
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(()->{
System.out.println("查询商品的图⽚信息");
return"hello.jpg";
},executor);
CompletableFuture<String> futureInfo = CompletableFuture.supplyAsync(()->{
System.out.println("查询商品属性");
return"⿊⾊ 256G";
},executor);
CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(()->{
System.out.println("查询商品介绍");
return"华为";
},executor);
五、多任务执⾏
1. allOf:全部线程结束以后才会执⾏
2. anyOf:只要有⼀个线程执⾏完成就会执⾏
/**
* allOf:全部线程结束以后才会执⾏
* anyOf:只要有⼀个线程执⾏完成就会执⾏
*/
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureInfo, futureDesc);
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureInfo, futureDesc); //        ();//等待所有结果完成
<();
//还可以得到上⾯的所有现成的结果
System.out.println("nd....."+()+()+());
六、项⽬实战
项⽬为SpringBoot项⽬,以获取商城商品信息为列:
配置类MyThreadPoolConfig

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。