怎么通过ThreadPoolExecutor的方式创建线程池

本篇文章给大家分享的是有关怎么通过ThreadPoolExecutor的方式创建线程池,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在 JDK1.5 以前,研发人员在面对线程频繁调度的场景,必须手动打造线程池,来节约系统开销(画外音:真是吃了不少苦头)。从 JDK1.5 开始,Java 提供了一个 Excutors 工厂类来生产线程池,可以帮助研发人员有效的进行线程控制(画外音:不用造轮子啦,爽歪歪)。

(配图释义:JDK 1.8 能用 Excutors 创建的线程池)
如上图示意,Excutors 提供了满足各种场景的线程池创建方式,Java研发人员就不用苦逼哈哈的去造轮子啦,谁用谁爽。
但是,阿里开发规约明确强制研发人员:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式。

不过,若经常关注源码的同学会发现,无论是 newFixedThreadPool() 方法、newSingleThreadExecutor() 方法,还是 newCachedThreadPool() 方法,其背后均使用了 ThreadPoolExecutor。
(配图释义:JDK 1.8 能用 Excutors 创建的线程池的背后)
通过上面源码截图,可以清晰看出,以上几种创建线程池的方式,均是对 ThreadPoolExecutor 类的封装,所以要想彻底掌握线程池,势必要吃透线程池背后的ThreadPoolExecutor。1解剖:构造函数有关 ThreadPoolExecute 构造函数,很多书上或者文章都会提到,下面再简单了解一下每个参数的具体含义。构造函数的参数释义:corePoolSize:指定线程池中的线程数量;maximumPoolSize:指定线程池中的最大线程数量;keepAliveTime:当线程池中线程数量超过 corePoolSize 时,空闲线程的存活时间;unit:keepAliveTime 的单位;workQueue:任务队列,存放提交尚未被执行的任务;threadFactory:线程工厂,用于创建线程,一般用默认的即可;handler:拒绝策略,当任务太多来不及处理,如何拒绝任务。以上参数除了 workQueue 以及 handler 外,大部分都很易懂。接下来重点说说 workQueue 以及 handler 两个参数。参数BlockingQueue workQueue,是用于存放提交尚未被执行的任务的队列,类型是 BlockingQueue 接口的对象,用于存放 Runnable 对象。参数RejectedExecutionHandler handler 是指当任务数量超过系统承载能力时,该如何处理?其中 JDK 提供了四种拒绝策略。(配图释义:JDK 1.8 内置的拒绝策略)JDK 提供的四种拒绝策略归纳,简单了解一下。
2了解完 ThreadPoolExecutor 类的构造函数,接下来探讨一下阿里开发手册明确强制的一条使用线程池的规约。

为了更清晰的认识,不妨走进源码看一看。首先走进 newFixedThreadPool() 方法的源码,一探究竟。

如源码截图所示,newFixedThreadPool() 方法的实现,返回一个 corePoolSize 和 maximumPoo 香港云主机lSize 大小一样的,并且使用了 LinkedBlockingQueue 任务队列的线程池。

如上面LinkedBlockingQueue 的源码所示,队列的默认长度为 Integer.MAX_VALUE,那么当任务提交频繁时,线程池中的线程处理不过来时,队列可能会迅速膨胀,从而会出现 OOM。
接着走进 newSingleThreadExecutor() 方法的源码,看看有没有新大陆。

如源码截图示意,newSingleThreadExecutor 方法实现中,corePoolSize 和 maximumPoolSize 设置的值均为 1,返回一个单线程的线程池,并且使用 LinkedBlockingQueue 任务队列来存在提交的任务,与newFixedThreadPool() 方法一样,当任务提交频繁时,线程池中的线程处理不过来时,队列会迅速膨胀,从而会出现 OOM。
最后看看newCachedThreadPool() 方法的源码实现,一探究竟。

如上图源码示意,newCachedThreadPool()方法实现,返回了一个corePoolSize 为 0,maximumPoolSize 的值为Integer.MAX_VALUE,并且使用 SynchronousQueue 作为任务队列的线程池。
而 SynchronousQueue队列是一种直接提交的队列(不会保存提交的任务),所以总会使线程池增加新的线程来执行任务,当任务执行完毕后,由于 corePoolSize 为 0,因此空闲线程又会在 60 秒内被回收。
如果同时有大量任务被提交,而任务的执行又不那么快时,newCachedThreadPool() 方法,便会开启大量的线程进行处理,这样可能很快耗尽系统的资源,进而导致 OOM。以上就是怎么通过ThreadPoolExecutor的方式创建线程池,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注开发云行业资讯频道。

相关推荐: Linux网络协议栈收消息过程是什么

本篇内容介绍了“Linux网络协议栈收消息过程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如果没有开启 RPS 会调用__netif_receive_s…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 09/23 19:34
下一篇 09/23 19:34

相关推荐

发表评论

您的电子邮箱地址不会被公开。