前言

最近看阿里的 Java开发手册,上面有线程池的一个建议:

【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,

这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

结合最近面试的经历,发现这条建议还是十分有用的,因为自己经常使用Executors提供的工厂方法创建线程池,所以忽略了线程池内部的实现。

特别是拒绝策略,面试被问到两次,因为使用Executors创建线程池不会传入这个参数而使用默认值所以我们常常忽略这一参数,还好因为这条建议,自己提前熟悉了一下ThreadPoolExecutor。

ThreadPoolExecutor

先看看如何使用ThreadPoolExecutor创建线程池:

    public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

corePoolSize - 线程池核心池的大小。

maximumPoolSize - 线程池的最大线程数。

keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

unit - keepAliveTime 的时间单位。

workQueue - 用来储存等待执行任务的队列。

threadFactory - 线程工厂。

handler - 拒绝策略。

关注点1 线程池大小

线程池有两个线程数的设置,一个为核心池线程数,一个为最大线程数。

在创建了线程池后,默认情况下,线程池中并没有任何线程,等到有任务来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法

当创建的线程数等于 corePoolSize 时,会加入设置的阻塞队列。当队列满时,会创建线程执行任务直到线程池中的数量等于maximumPoolSize。

关注点2 适当的阻塞队列

java.lang.IllegalStateException: Queue full

方法 抛出异常 返回特殊值 一直阻塞 超时退出

插入方法 add(e) offer(e) put(e) offer(e,time,unit)

移除方法 remove() poll() take() poll(time,unit)

检查方法 element() peek() 不可用 不可用

ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。

LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。

PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。

DelayQueue: 一个使用优先级队列实现的无界阻塞队列。

SynchronousQueue: 一个不存储元素的阻塞队列。

LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。

LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。

关注点3 明确拒绝策略

ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

说明:Executors 各个方法的弊端:

1)newFixedThreadPool 和 newSingleThreadExecutor:

主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。

2)newCachedThreadPool 和 newScheduledThreadPool:

主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。

Executors

让我们再看看Executors提供的那几个工厂方法。

newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。

此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

new ThreadPoolExecutor(1, 1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())

newFixedThreadPool

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。

线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,

那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。

此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());

JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法的更多相关文章

  1. 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

    jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–Execut ...

  2. 从阿里Java开发手册学习线程池的正确创建方法

    前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更 ...

  3. 阿里 JAVA 开发手册 学习 4 工程规约

    应用分层 1.分层如下 1)开放接口层:可以直接封装Service接口暴露成RPC:通过web封装成http接口:网关控制层等. 2)终端显示层:各个端的模板渲染并执行显示层. 3)Web层:主要是度 ...

  4. 阿里Java开发手册学习 3 MYSQL规约

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  5. 阿里Java开发手册学习 2 异常日志

    异常日志 异常处理 1.不要捕获继承自RuntimeException的运行时异常类,这类异常通常由程序员来校验,来保证查询的健壮性. 2. 不要对大段代码 try catch,分清稳定代码和非稳定代 ...

  6. 阿里JAVA开发手册零度的思考理解(一)

    转载请注明原创出处,谢谢! 缘由 阿里JAVA开发手册已经发表有很长时间了,值得认真研究思考推广 阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的哲学,值得好 ...

  7. 阿里JAVA开发手册零度的思考理解(二)

    转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...

  8. 阅读阿里Java开发手册记录

    概述 在阅读完阿里Java开发手册(嵩山版)后,发现自己在开发过程中有一些没有按照规范开发的情况,这里将容易忘记的规范记录下来,并且添加自己的理解,一方面方便自己巩固记忆,另一方面希望对其他同学能够提 ...

  9. 阿里java开发规范学习(附P3C IDEA插件 帮助规范的养成)

    浅析 阿里巴巴 Java 开发规约 (未完成) 更加优秀的页面展现请到浅析 阿里巴巴 Java 开发规约 contents 为什么要学 编程规约 P3C IDEA 插件 why-use 我们知道,一般 ...

随机推荐

  1. 2016年最全面的VR资源盘点,不只有VR视频播放器还有具体到步骤的VR资源

    2016年过去了,有多少人开始使用VR来观看我们喜欢的视频资源呢?比传统视频更高的沉浸感,甚至在VR眼镜的视角中,自己仿佛化生成视频中的主角一般.然而,这种体验只有VR眼镜还是不行的,还需要有一个VR ...

  2. Incompatible pointer types assigning to 'id<>' from 'Class'错误

    实例变量在类方法中被使用 原因:静态方法访问了非静态变量属性(.h中声明的那些属性),就是类方法访问了成员变量

  3. STM32 USB 问题汇总(转)

    源:STM32 USB 问题汇总 汇总1:STM32的USB例程修改步骤,来自http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx 以下 ...

  4. 微信小程序之----消息提示框toast

    toast toast为消息提示框,无按钮,如需关闭弹框可以添加事件设置hidden为true,在弹框显示后经过duration指定的时间后触发bindchange绑定的函数. 官方文档 .wxml ...

  5. eclipse安装maketplace插件

    对于默认eclipse是没有marketplace插件的,但是marketplace确实是非常好用的,可以在上面下载各种插件. 1.Help-->Install new Software 2.输 ...

  6. python 数组的del ,remove,pop区别

    以a=[1,2,3] 为例,似乎使用del, remove, pop一个元素2 之后 a都是为 [1,3], 如下: >>> a=[1,2,3] >>> a.rem ...

  7. Python3基础 用 while循环实现 斐波那契数列

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  8. linux上编译安装python2.7.5

    下载python2.7.5,保存到 /data/qtongmon/software http://www.python.org/ftp/python/ 解压文件 tar xvf Python-2.7. ...

  9. Zepto.js-Ajax 请求

    Ajax 请求 执行Ajax请求.它可以是本地资源,或者通过支持HTTP access control的浏览器 或者通过 JSONP来实现跨域. 引入Ajax模块 <script src=&qu ...

  10. Mysql中日期时间型解析