线程池(Executors)
・
代码实现:
・
Runnable设置线程任务
・
・
・
常见的4种线程池
・
1 Executors.newCacheThreadPool(): 可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务。 线程池核心线程大小=0;都可回收
2 Executors.newFixedThreadPool(int n): 创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程。线程池核心线程大小=线程池最大线程数量都不可回收
3 Executors.newScheduledThreadPool(int n): 创建一个定长线程池,支持定时及周期性任务执行。做定时任务的线程池
4 Executors.newSingleThreadExecutor(): 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。单线程的线程池,后台从队列里面获取任务,挨个执行。
・
・
创建线程池
・
ExecutorService es = Executors.newFixedThreadPool(2);
・
提交异步任务到线程池
・
・
1、Executors.submit(new RunnableImpl()); //有返回值
2、Executors.execute(new RunnableImpl()); //无返回值
・
原始线程池创建
线程池的七大参数
・
・
一、corePoolSize 线程池核心线程大小
线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会 被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。
・
・
二、maximumPoolSize 线程池最大线程数量
一个任务被提交到线程池后,首先会缓存到工作队列(后面会介绍)中,如果工作队列满了,则会创建一个新线程,然后从工作队列中的取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize来指定。
三、keepAliveTime 空闲线程存活时间
一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定
四、unit 空间线程存活时间单位
keepAliveTime的计量单位
五、workQueue 工作队列
新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:
①ArrayBlockingQueue
基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
②LinkedBlockingQuene
基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。
③SynchronousQuene
一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
④PriorityBlockingQueue
具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
六、threadFactory 线程工厂
创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等
七、handler 拒绝策略
当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,该如何处理呢。这里的拒绝策略,就是解决这个问题的,jdk中提供了4中拒绝策略:
①CallerRunsPolicy
该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
②AbortPolicy
该策略下,直接丢弃任务,并抛出RejectedExecutionException异常
③DiscardPolicy
该策略下,直接丢弃任务,什么都不做。
④DiscardOldestPolicy
该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
・
・
・
异步编排
・
1、创建异步对象 CompletableFuture
・
2、异常处理
・
CompletionStage exceptionally(fn);
CompletionStage whenComplete(consumer);
CompletionStage whenCompleteAsync(consumer);
CompletionStage handle(fn);
CompletionStage handleAsync(fn);
whenComplete() 和 exceptionally() 、handle()系列方法就类似于 try{}finally{}中的 finally{}, 无论是否发生异常都会执行 whenComplete() 中的回调函数 consumer 和 handle() 中的回调函数 fn。
whenComplete() 和 exceptionally()、handle() 的区别在于 whenComplete() 不支持返回结果,而 exceptionally()、handle() 是支持返回结果的。
・
・
・
・
・
3、线程串行化方法
・
thenApply、thenAccept、thenRun、thenCompose
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);
public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,Executor executor);
thenApply 系列函数里参数 fn 的类型是接口 Function<T, R>,这个接口里与 CompletionStage 相关的方法是R apply(T t),这个方法既能接收参数也支持返回值,所以 thenApply 系列方法返回的是CompletionStage。
而 thenAccept 系列方法里参数 consumer 的类型是接口Consumer<>,这个接口里与 CompletionStage 相关的方法是void accept(T t),这个方法虽然支持参数,但却不支持回值,所以 thenAccept 系列方法返回的是CompletionStage Void
thenRun 系列方法里 action 的参数是 Runnable,所以 action 既不能接收参数也不支持返回值,所以 thenRun 系列方法返回的也是CompletionStage 《void》
这些方法里面 Async 代表的是异步执行 fn、consumer 或者 action。其中,需要你注意的是 thenCompose 系列方法,这个系列的方法会新创建出一个子流程,最终结果和 thenApply 系列是相同的。
・
・
4、描述 AND 汇聚关系
・
CompletionStage 接口里面描述 OR 汇聚关系,主要是 applyToEither、acceptEither 和 runAfterEither 系列的接口,这些接口的区别也是源自 fn、consumer、action 这三个核心参数不同。
CompletionStage<R> thenCombine(other, fn);
CompletionStage<R> thenCombineAsync(other, fn);
CompletionStage<Void> thenAcceptBoth(other, consumer);
CompletionStage<Void> thenAcceptBothAsync(other, consumer);
CompletionStage<Void> runAfterBoth(other, action);
CompletionStage<Void> runAfterBothAsync(other, action);
CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);
・
runAfterBothAsync(other, action)示例 不能感知前面函数的结果,没有返回值
・
・
・
thenAcceptBothAsync(other, consumer);示例能感知到前面任务返回的结果,无返回值
・
・
・
thenCombineAsync(other, fn);示例能感知到前面任务返回的结果,有返回值
・
・
・
runAfterEitherAsync(other, action); 两个任务,一个完成就能执行这个方法,不感知结果,自己也没有返回值
・
・
acceptEitherAsync(other, consumer); 两个任务,一个完成就能执行这个方法,能接收上面方法的返回结果,但是也没有返回值。
・
・
applyToEitherAsync(other, fn); 能感知结果,而且有返回值。
・
・
・
・
5、多任务组合
・
・
allof 顾名思义,就是所有的任务执行完成后返回future
・
・
・
anyof 就是只要有一个任务执行完成后就返回future并将第一个完成的参数带着一起返回
・
・
・
・
异步代码示例
・
//1、sku基本信息的获取 pms_sku_info执行完后,//2、sku图片信息 pms_sku_images 异步执行
・
//1、sku基本信息的获取 pms_sku_info执行完后, //3、获取spu销售属性组合、 //4、获取spu介绍 pms_spu_info_desc 图片信息介绍、 //5、获取spu规格参数信息 (所有属性值 主体)异步执行
・
SkuItemVo skuItemVo = new SkuItemVo();
//1、Sku基本信息 pms_sku_info
CompletableFuture<SkuInfoEntity> infofuture = CompletableFuture.supplyAsync(() -> {
//1、sku基本信息的获取 pms_sku_info
SkuInfoEntity info = this.getById(skuId);
skuItemVo.setInfo(info);
return info;
}, executor);
CompletableFuture<Void> saleAttrfuture = infofuture.thenAcceptAsync((res) -> {
//3、获取spu销售属性组合
List<SkuItemSaleAttrVo> saleAttrVo = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVo);
}, executor);
CompletableFuture<Void> descfuture = infofuture.thenAcceptAsync((res) -> {
//4、获取spu介绍 pms_spu_info_desc 图片信息介绍
SpuInfoDescEntity spuInfo = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesp(spuInfo);
}, executor);
CompletableFuture<Void> baseAttrfuture = infofuture.thenAcceptAsync((res) -> {
//5、获取spu规格参数信息 (所有属性值 主体)
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsByspuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(attrGroupVos);
}, executor);
//2、sku图片信息 pms_sku_images
CompletableFuture<Void> imagesfuture = CompletableFuture.runAsync(() -> {
List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(images);
}, executor);
//等待所有任务都完成
CompletableFuture.allOf(saleAttrfuture,descfuture,baseAttrfuture,imagesfuture).get();
return skuItemVo;