3.这三种创建线程池的方式有风险,慎用!

创建线程池的方式多种多样,但这三种千万别用在正式环境中,他们分别是固定大小的线程池和单个线程的线程池以及可缓存的线程池。

 

 

 

究竟有何风险,呆会儿再具体介绍他们的时候再说。这三种创建方式都在一个executors工具类中,

 

 

所有以new开头的方法都可以创建线程池,

 

 

一共有12个这样的方法,去掉重载方法后也就剩下六个。

 

 

看似方式繁多,其实搞懂他们一点都不难,因为他们都和threadpoolexecutor有直接或间接的关系

 

threadpoolexecutor是创建线程池的原生方式,把它搞明白了,其他的都是小菜一碟。

threadpoolexecutor在上一节已经详细介绍过,这里就不再赘述了。这三种方式内部都采用threadpoolexecute来创建线程池,只不过做了一些简化参数的工作,接下来我们就依次来。

这三种创建线程池的方式,

 

 

 

Fixedthreadpool固定大小的线程池

它内部采用threadpoolexecutor来创建线程值,并且核心线程数和最大线程数一样,意味着它里面全部都是核心线程

 

 

 

 

 

空闲线程存活时间为零毫秒,这样空闲线程就不会被销毁。任务队列采用的是linkedblockingqueue,需要注意的是此队列有资源耗尽的风险,因为linkedblockingqueue的容量为integer的最大值,而integer的最大值是二的31次方,意味着任务队列中的任务数量可高达20亿之多,哪有那么大的内存给他装,内存随时都有可能爆掉。所以fixedthreadpool这种创建方式极力不推荐大家使用。

 

 

 

 

 

另外,在阿里巴巴Java开发手册的第一章第七小节第四条中这样写道,Fixedthreadpool和singlethreadpool允许的请求队列长度为integer.maxvalue,可能会堆积大量的请求,从而导致OOM,在阿里内部直接就明令禁止使用它们来创建线程池。禁止归禁止,演示总归还是要演示的。

 

 

 

创建固定大小的线程池有两个方法,一个不带现成工厂,一个带现成工厂。接下来我们来演示不带线程工厂的方法.

 

 

 

不带线程工厂

编写一个任务,任务内容是输出当前线程名称,接下来我们来执行该任务。

 

 

 

首先创业出三个任务,然后创建一个固定大小的线程池,并指定线程数量为十,接下来向线程池中提交任务,最后别忘了关闭线程池。至此方法编写完成,整个例子也编写完成。

 

 

 

执行程序,观察执行结果。从执行结果来看,程序输出三个不同的线程名称。

 

 

 singlethreadexecutor单个线程的线程池

看完了固定大小的线程池。再来看看singlethreadexecutor单个线程的线程池,它内部也采用threadpoolexecute来创建。

 

 

 

键值,并且核心线程数和最大限制数一样,都是一,意味着它里面也全都是核心线程,只不过只有一个空闲线程,存活时间为零毫秒,这样它里面的空闲线程也不会被销毁。任务队列采用的是linkedblockingto风险我在这里就不再赘述了,和fixedthreadpool一样的问题,所以newsinglethreadexecutor这种方式也不推荐大家使用。

 

 

 

创建单个线程的线程池有两个方法,一个不带现成工厂,一个带现成工厂。

 

 

 不带现成工厂的方法

接下来我们也是不带现成工厂的方法,还是沿用之前的例子,将固定大小的线程池改为单个线程的线程池。

 

 

 

例子修改完毕,执行修改后的程序,观察执行结果,从执行结果来看,程序输出三个一样的线程名称,说明线程池中的确只有一个线程。

 

 

 cachedthreadpool可缓存的线程池

看完了单个线程的线程池,再来看看cachedthreadpool可缓存的线程池

除了核心线程以外,还有非核心线程,它内部也采用threadpoolexecute来创建线程池。

 

 

 

核心线程数是零,意味着可缓存的线程池里面全部都是非核心线程,非核心线程空闲下来是要被销毁的,最大线程数是integer的最大值,风险不言而喻。同样是第四条弊端就不再赘述了,所以和前面两个现实的问题一样,Cachedthreadpool也不推荐大家使用。空闲线程存活时间为60秒,意味着空闲线程60秒内没工作就会被销毁。

 

 

 

 

任务队列采用的是synchronousqueue,这是一个同步队列。创建可缓存的线程池有两个方法,一个不带线的工厂,一个带现成工厂。

 

 不带现成工厂的方法

接下来我们也是不带现成工厂的方法,还是沿用之前的例子,将单个线程的线程池改为可缓存的线程池。

 

 

例子修改完毕,执行修改后的程序,观察执行结果。

 

 

从执行结果来看,程序输出三个不一样的线程名称。

总结

最后总结一下本节内容。本节介绍了固定大小的线程池和单个线程的线程池以及可缓存的线程池,这三个线程池都有资源耗尽的风险,

不推荐大家在生产环境中使用,推荐大家通过原生的方式来创建线程池。

 

 

 

 

posted @   小陈子博客  阅读(567)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示