ThreadPoolExecutor实战(二:线程池创建方式、多线程调度实战)

上篇博客介绍了线程池参数配置,下面结合案例看一下创建方式

1.原生方式

上图我自己new了一个ThreadPoolExecutor对象,当然ThreadPoolExecutor需要在全局声明,否则会重复创建多个线程池,这里只是测试,所以不必纠结这里的局部声明方式。上面我使用了CompletableFuture去申请调度,然后模拟了一个拒绝策略触发条件。最终的运行结果是主线程阻塞在49行代码。所以这个地方需要注意的是拒绝策略这里,如果真到到了负载阀值,在配合CompletableFuture的时候需要做一些拒绝策略异常抛出,然后try住submit动作,否则这个得不到调度的线程会在allOf join时阻塞整个主线程。

ok,把join换为1.6的实现看看


我把CompletableFuture换为CountDownLatch,同样实现一个多线程调度,主线程join所有task结束的操作。

最终运行结果是最后一个拒绝的task仍然阻塞,但是其他task正常输出。此时代码运行阻塞在了52行最后一次循环。

笔者上周就因为使用了第一种CompletableFuture allOf join操作碰到了线程数超过阀值而未使用submit异常丢弃处理产生了主线程阻塞,整个rpc请求超时引起熔断。这点大家需要在使用过程中注意。

如果大家调大为上述代码中的队列长度或者最大线程数,这个案例将正常打印所有输出,我只是模拟一下峰值扛不住的场景。

当然以上方式,也可以通过spring管理

2.spring方式


只需要跟上图一样将自己配置的ThreadPoolExecutor注入到spring容器,就可以以autowared等方式在其他类中全局引用,或者在静态方法中通过工具类实现ApplicationContextAware接口拿到applicationContext获取bean。

下面看一下Executors和spring线程池

上图已经展示了spring线程池等配置,第一个bean就是spring线程池实现,参数名就可以看出参数含义,所以不一一介绍了。

具体表现大家可以自己测试,实践出真知

最后介绍一下Executors实现

3.Executors方式

Executors实现的线程池就是以上述方式创建,底层就是去构造一个ThreadPoolExecutor构造函数。

但是它内部的实现(比如fix池没有队列长度限制),可能会造成内存泄漏或者cpu太密集,所以建议大家对于线程池理解够深的话,尽量是自己去配置,而不使用这种最简单的方式。

以上代码均在博主的基佬hub中:https://github.com/Spring5945/Concurrent

感兴趣的可以pull下来自己跑跑看,博主比较懒,更新比较慢,但是这不是你们不点star的理由。

下一节主要讲解线程池调优,以及针对cpu密集型和io密集型系统参数选择。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 【JAVA 线程】 线程 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者...
    Rtia阅读 2,890评论 2 20
  • 今天和小杰仔一起共读了两本书,一本是《蹦》一本是《猜猜我是谁》。 《蹦》是今天早上早饭后,小杰仔自己在爬爬垫上拿过...
    忆记阅读 276评论 0 0
  • 大学毕业快两年半,因为工作方面的原因,选择了回老家工作。其实是不甘心的,一心想着翅膀硬了再飞出去,于是每天看书写字...
    d828547474e8阅读 190评论 0 0
  • 虽然我也无法接受这个怪胎,但是挺佩服他的坚持劲儿,坚持不要脸,坚持死不要脸,最后他终于做到了!商业演出已经排到20...
    Dave云阅读 311评论 1 0
  • 寒假放假在家,本以为各种微信群,QQ群会寂寥无声,没想到,却天天炸开了锅。一打开QQ,群里99+的消息,微信群几百...
    有范柠萌阅读 2,010评论 0 0

友情链接更多精彩内容