美文网首页多线程我爱编程
ThreadPoolExecutor实战(二:线程池创建方式、多

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

作者: 但时间也偷换概念 | 来源:发表于2018-05-27 19:11 被阅读0次

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

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密集型系统参数选择。

相关文章

网友评论

    本文标题:ThreadPoolExecutor实战(二:线程池创建方式、多

    本文链接:https://www.haomeiwen.com/subject/ujqijftx.html