2.为什么推荐使用原生方式创建线程池?
线程池的创建
创建线程池的方式一共有八种,
但万变不离其宗,这个宗就是原生创建线程池的方式,这种方式也是阿里极力推荐的一种。在阿里巴巴Java开发手册的第七章第四小节中这样写道,线程时不允许一个executors去创建,而是通过threadpoolExecutor的方式去创建,其他的创建方式有资源耗尽的风险。
后续章节再介绍其他创建方式时也会提到,这是上一节展示的线程池核心UML类图,从图中我们可以看到,能实例化的只有这两个
Threadpoolexecutor和scheduledthreadpoolexecutor,其中有一个类是线程池的核心类,它就是threadpoolexcuteor,它一共有四个构造方法,不过都大同小异。最后一个构造方法参数最多,我们就从他开始,该方法一共有七个参数,七个参数的含义如图所示,
corepoolsize。
核心线程数具体什么意思?把接下来的三个参数看完,一起说,Maximumpoolsize,最大线程数,
Keepalivetime,空闲线程存活时间,Unite,时间单位。这四个参数要一起看才更容易理解。这里我把四个参数都列举出来,并给他们附上值。
核心线程数是十,最大线程数是25,空闲线程存活时间是10,时间单位是timeunit..seconds也就是秒结和第三个参数合起来就是空闲线程的存活时间是十秒,十秒内没工作就会被销毁,如果空闲时间是零的话,空闲线程不会被销毁。所有参数都附上了,
直接下来我们就来创建这样一个线程池,首先是核心线程,事实表示线程池中有十个核心线程,
出,好处就是只要线程池不关闭,它就不会被销毁。
再来看第二个参数,最大线程数是25,表示线程池中最多允许有25个线程,那么在这25个线程当中,除去核心线程之外的线程是什么?是非核心线程,
非核心线程没有执行任务的话是要被清理的,在被清理之前能存活多久取决于第三个参数和第四个参数,
这是线程池中所有线程都在工作的场景,
当任务都执行完以后,
所有线程都成了空闲线程。
当然了,还是分核心和非核心,只不过再过十秒,
如果非核心线程门还没有工作,那就要被销毁,剩下的都是核心线程。
到这里,相信这四个参数你已经懂了。
workqueue
workqueue、任务队列、存放任务的容器、提交给线程池的任务都存在这儿,线程池中的线程们也都是在这儿领取的任务,
我一般用的是linkedBlockingqueue,链式阻塞队列,这是一个基于链表的阻塞队列
.还有一个常用的是arrayblockingqueue数组阻塞队列,这是一个基于数组的阻塞队列。除此以外,大家还可以尝试其他的阻塞队列。
threadfactory线程工厂
threadfactory线程工厂,顾名思义,可以指定线程该如何生产,它是一个接口,实现它里面new thread()方法可以自定义线程的相关设置,例如我们可以指定线程名称,还可以指定线程是否为后台线程等等其他一些设置。
如果你不想自定义线程工厂,那么你也可以使用executeers内中的默认线程工厂。实际开发中我一般自定义得多,因为可以自定义线程名称,方便我后续查看日志。
Handler任务拒绝策略
再来看最后一个参数,Handler任务拒绝策略。
在什么情况下我们提交给限制时的任务会被拒绝?同时满足以下这四种情况,我们提交给线程池的任务。会被拒绝。
第一种情况,线程池中的线程已满,
第二种情况,无法再继续扩容,
第三种情况,没有空闲线程,所有的线程都在执行任务,
第四种情况,任务队列已满,无法再存入新任务。
同时满足这四个条件时,我们提交给线程池的任务才会被拒绝。
线程池拒绝我们的方式也有四种,如图所示,这里就不再展开讲了,或许会单独出一个章节来讲任务拒绝策略,
呆会儿我们就用默认的拒绝策略回到构造方法,所有的参数也介绍完毕,接下来使用原生方法创建线程池。
线程工厂创建
我们先制定一个线程工厂,定义一个类customthreadfactory,实现threadfactory接口,重写new rhread方法的方法,定义一个计数器atomicinteger类型,这样就不会出现线程安全问题,初始值为一,该计数器用在线程名称中,给线程编号创建线程。
实例并指定任务自定义线程名称,每创建一个线程,
计数器递增一次,最后返回线程实例自定义线程工厂编写完成。
任务编写
接下来编写一个任务,任务内容是输出当前线程名称,我们来执行该任务。首先创建出三个任务,然后创建一个线程池,核心线程数为十,最大线程数为25,空闲线程存活时间为什,时间单位为秒。任务队列采用链式阻塞队列,线程工厂为刚刚自定义的线程工厂。任务拒绝策略采用的是默认任务拒绝策略。接下来像现实中提交任务,最后别忘了关闭线程池。至此main方法编写完成,整个例子也编写完成。
执行程序,观察执行结果。从执行结果来看,程序输出线程1,2,3,证明我们自定义的线程工厂生效了,使用原生方式创建线程池。成功最后总结一下本节的内容,本节介绍了如何使用原生方式创建线程直,这种方式是阿里极力推荐的一种,也是我日常开发中使用的最多的一种。
本文来自博客园,作者:小陈子博客,转载请注明原文链接:https://www.cnblogs.com/cj8357475/p/16015874.html