【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法
jdk1.7中java.util.concurrent.Executor线程池体系介绍
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|–ExecutorService:Executor的子接口,线程池的主要接口
|–ThreadPoolExecutor:ExecutorService的实现类
|–ScheduledExecutorService:ExecutorService的子接口,负责线程的调度
|–ScheduledThreadPoolExecutor:既继承了ThreadPoolExecutor,同时实现了ScheduledExecutorService
在实际使用过程中,我们不需要自己手动new出线程池,juc的工具类Executors为我们提供了方法用以创建线程池: (注意:最近阿里发布的 Java开发手册中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。下面转载部分有较为详细的介绍)
ExecutorService newFixedThreadPool() : 创建固定大小的线程池
ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。
ExecutorService newSingleThreadExecutor() : 创建单个线程池。线程池中只有一个线程
ScheduledExecutorService newScheduledThreadPool() : 创建固定大小的线程池,可以延迟或定时的执行任务。
转载部分:
前言
最近看阿里的 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>());
转载自:http://www.cnblogs.com/javanoob/p/threadpool.html
【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法的更多相关文章
- JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法
前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学 ...
- 从阿里Java开发手册学习线程池的正确创建方法
前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更 ...
- 阿里 JAVA 开发手册 学习 4 工程规约
应用分层 1.分层如下 1)开放接口层:可以直接封装Service接口暴露成RPC:通过web封装成http接口:网关控制层等. 2)终端显示层:各个端的模板渲染并执行显示层. 3)Web层:主要是度 ...
- 阿里Java开发手册学习 3 MYSQL规约
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- 阿里Java开发手册学习 2 异常日志
异常日志 异常处理 1.不要捕获继承自RuntimeException的运行时异常类,这类异常通常由程序员来校验,来保证查询的健壮性. 2. 不要对大段代码 try catch,分清稳定代码和非稳定代 ...
- 阿里JAVA开发手册零度的思考理解(一)
转载请注明原创出处,谢谢! 缘由 阿里JAVA开发手册已经发表有很长时间了,值得认真研究思考推广 阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的哲学,值得好 ...
- 阅读阿里Java开发手册记录
概述 在阅读完阿里Java开发手册(嵩山版)后,发现自己在开发过程中有一些没有按照规范开发的情况,这里将容易忘记的规范记录下来,并且添加自己的理解,一方面方便自己巩固记忆,另一方面希望对其他同学能够提 ...
- 阿里JAVA开发手册零度的思考理解(二)
转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...
- 品阿里 Java 开发手册有感
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图, ...
随机推荐
- 32. Longest Valid Parentheses(最长括号匹配,hard)
Given a string containing just the characters '(' and ')', find the length of the longest valid (w ...
- JAVA中hashmap的分析
从http://blog.csdn.net/luanlouis/article/details/41576373?utm_source=tuicool&utm_medium=referral学 ...
- python-静态方法staticmethod、类方法classmethod、属性方法property
Python的方法主要有3个,即静态方法(staticmethod),类方法(classmethod)和实例方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def ...
- qemu-nbd方式挂载qcow2镜像
客户端配置 加载nbd模块 [root@centos sm]# rmmod nbd [root@centos sm]# modprobe nbd max_part=8 映射服务器的块设备到本地nbd设 ...
- 关于hashmap 与concurrentHashMap
hashmap是不安全的,要实现安全,可以用Collections里面的synchronizedMap包裹来实现安全,或者用concurrentMap, 注意:hashtable是安全的 从JDK1. ...
- SQL统计信息解释
[SQL基础]统计信息解释 在平时优化SQL的时候,最长用的就是:SET STATISTICS ON,它可以用来查看我们写的查询语句到底性能如何,不过,究竟这个性能的指标是怎么样的呢?首先需要明白的, ...
- Java Mail 邮件发送Demo
上周公司的项目要求开发邮件发送功能.自己在网上跟着教程边学边做了一下午,现在基本开发完成了.由于一个同事也想看下该怎么写,顺便学习下.所以我就写成了一遍教程,顺便巩固下邮件发送里面的内容. Demo ...
- 使用BusyBox制作根文件系统
1.BusyBox简介 BusyBox 是很多标准 Linux 工具的一个单个可执行实现.BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大.更复杂的工具,例如 gre ...
- 2019 google kickstart round A
第一题: n个人,每个人有一个对应的技能值s,现在要从n个人中选出p个人,使得他们的技能值相同. 显然,如果存在p个人的技能值是相同的,输出0就可以了.如果不存在,就要找出p个人,对他们进行训练,治他 ...
- Swift学习笔记 - URL编码encode与解码decode
使用swift有一段时间了,api的变换造成了很多困扰,下面是关于url编码和解码问题的解决方案 在Swift中URL编码 在Swift中URL编码用到的是String的方法 func addingP ...