线程池之ThreadPoolExecutor
所属包:
java.util.concurrent.ThreadPoolExecutor
类关系:
public class ThreadPoolExecutor extends AbstractExecutorService
1. 继承关系
ThreadPoolExecutor 继承了一个抽象类:AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService
而这个AbstractExecutorService实现了一个接口:ExecutorService
public interface ExecutorService extends Executor
这个ExecutorService接口又继承了一个类:Executor
public interface Executor
可以看出:
Executor是一个顶层接口,它的子接口ExecutorService继承了它(其实还有一个子接口: ScheduledExecutorService),抽象类AbstractExecutorService实现了这个子接口ExecutorService,最终ThreadPoolExecutor 继承了抽象类AbstractExecutorService并且同时实现了子接口ExecutorService。
2. 构造方法
最简单的一个构造方法:
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory and rejected execution handler.
* It may be more convenient to use one of the {@link Executors} factory
* methods instead of this general purpose constructor.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
有五个参数:
corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 在执行任务之前用于保存任务的队列。 该队列将仅保存execute方法提交的Runnable任务
实际上它调用了同类的另外一个构造方法,最后两个参数用的默认值
另外一个构造方法:
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
参数:
corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂
handler - 执行被阻止时使用的处理程序,因为达到线程限制和队列容量 (拒绝策略)
3. 如何使用
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class MyThreadPoolExecutor { /**
* 使用有界队列:
* 1、当线程数小于corePoolSize时,创建线程执行任务。
* 2、当线程数大于等于corePoolSize并且workQueue没有满时,放入workQueue中
* 3、线程数大于等于corePoolSize并且当workQueue满时,新任务新建线程运行,线程总数要小于maximumPoolSize
* 4、当线程总数等于maximumPoolSize并且workQueue满了的时候执行handler的rejectedExecution。也就是拒绝策略。
*
* ThreadPoolExecutor默认有四个拒绝策略:
* 1、ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
* 2、ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
* 3、ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
* 4、ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务
*
*
*
*/ public static void main(String[] args) { ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3)); Runnable[] runs = new Runnable[6];
for (int i = 0; i < runs.length; i++) {
runs[i] = new MyTask(i);
} pool.execute(runs[0]); //线程1个,队列0个
pool.execute(runs[1]); //线程1个,队列1个
pool.execute(runs[2]); //线程1个,队列2个
pool.execute(runs[3]); //线程1个,队列3个
pool.execute(runs[4]); //线程2个,队列3个
pool.execute(runs[5]); //线程2个,队列3个,拒绝第六个 pool.shutdown(); }
}
线程:
public class MyTask implements Runnable {
private int id;
public MyTask(int id) {
this.id = id;
}
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task-" + id);
}
}
这个就是最简单的一个使用方法了。ps:最后那个(线程1个,队列0个....)指的是,你仅仅执行runs[0];runs[0]+runs[1];runs[0]+runs[1]+runs[2];....的时候,任务被放到哪里。
但是推荐使用这种方式创建线程池:
package cn.ying.thread.pool; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class MyTest { public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) {
pool.execute(new MyTask(i));
}
pool.shutdown();
} public void note(){
Executors.newCachedThreadPool(); //无界线程池,可以进行自动线程回收
// public static ExecutorService newCachedThreadPool() {
// return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
// 60L, TimeUnit.SECONDS,
// new SynchronousQueue<Runnable>());//SynchronousQueue:长度为1的队列
// }
Executors.newFixedThreadPool(10); //创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
// public static ExecutorService newFixedThreadPool(int nThreads) {
// return new ThreadPoolExecutor(nThreads, nThreads,
// 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>());
// }
Executors.newScheduledThreadPool(10); //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行
// public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
// return new ScheduledThreadPoolExecutor(corePoolSize);
// }
// public ScheduledThreadPoolExecutor(int corePoolSize) {
// super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
// new DelayedWorkQueue());
// }
Executors.newSingleThreadExecutor(); //创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
// public static ExecutorService newSingleThreadExecutor() {
// return new FinalizableDelegatedExecutorService
// (new ThreadPoolExecutor(1, 1,
// 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>()));
// } }
}
==============================更新
4. 拒绝策略
1. AbortPolicy(丢弃任务并抛出RejectedExecutionException异常)默认策略
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args) throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
// 拒绝并抛出异常
new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 6; i++){
pool.execute(new Task("任务" + i));
}
pool.shutdown();
} private static class Task implements Runnable{
private String name; Task(String name) {
this.name = name;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "===" + name);
}
} }
运行:

2. DiscardPolicy(丢弃任务,但是不抛出异常)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args) throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
// 拒绝但不抛出异常
new ThreadPoolExecutor.DiscardPolicy()); for (int i = 0; i < 6; i++){
pool.execute(new Task("任务" + i));
}
pool.shutdown();
} private static class Task implements Runnable{
private String name; Task(String name) {
this.name = name;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "===" + name);
}
} }
运行:

3. DiscardOldestPolicy(丢弃队列最前面的任务,然后重新提交被拒绝的任务)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args) throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
// 丢弃队列中最前面的任务,然后执行被拒绝的任务
new ThreadPoolExecutor.DiscardOldestPolicy()); for (int i = 0; i < 6; i++){
pool.execute(new Task("任务" + i));
}
pool.shutdown();
} private static class Task implements Runnable{
private String name; Task(String name) {
this.name = name;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "===" + name);
}
} }
运行:

4. CallerRunsPolicy(由提交任务的线程处理)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args) throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
// 由提交任务的线程直接执行此任务
new ThreadPoolExecutor.CallerRunsPolicy()); for (int i = 0; i < 6; i++){
pool.execute(new Task("任务" + i));
}
pool.shutdown();
} private static class Task implements Runnable{
private String name; Task(String name) {
this.name = name;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "===" + name);
}
} }
运行:

5. 自己处理
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args) throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
// 自定义处理
(Runnable r, ThreadPoolExecutor executor) -> {
System.out.println("自定义处理");
}); for (int i = 0; i < 6; i++){
pool.execute(new Task("任务" + i));
}
pool.shutdown();
} private static class Task implements Runnable{
private String name; Task(String name) {
this.name = name;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "===" + name);
}
} }
运行:

线程池之ThreadPoolExecutor的更多相关文章
- 从源码解读线程(Thread)和线程池(ThreadPoolExecutor)的状态
线程是比进程更加轻量级的调度执行单位,理解线程是理解并发编程的不可或缺的一部分:而生产过程中不可能永远使用裸线程,需要线程池技术,线程池是管理和调度线程的资源池.因为前不久遇到了一个关于线程状态的问题 ...
- Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析
目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...
- 线程池 一 ThreadPoolExecutor
java.util.concurrent public class ThreadPoolExecutor extends AbstractExecutorService ThreadPoolExecu ...
- 线程池之 ThreadPoolExecutor
线程池之 ThreadPoolExecutor + 面试题 线程池介绍 线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销. ...
- 高并发之——不得不说的线程池与ThreadPoolExecutor类浅析
一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但为什么在JDK1.5中又提供了线程池技术呢?这个问题大家自行脑补,多动脑,肯定没坏处,哈哈哈... 说起Java中的线程池技术,在很多 ...
- 【高并发】不得不说的线程池与ThreadPoolExecutor类浅析
大家好,我是冰河~~ 今天,我们一起来简单聊聊线程池中的ThreadPoolExecutor类,好了,不多说了,开始进入今天的正题. 一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但 ...
- 线程池:ThreadPoolExecutor
[ThreadPoolExecutor的使用和思考] public ThreadPoolExecutor(int corePoolSize, ...
- Java线程池之ThreadPoolExecutor
前言 线程池可以提高程序的并发性能(当然是合适的情况下),因为对于没有线程的情况下,我们每一次提交任务都新建一个线程,这种方法存在不少缺陷: 1. 线程的创建和销毁的开销非常高,线程的创建需要时间, ...
- 从源码看JDK提供的线程池(ThreadPoolExecutor)
一丶什么是线程池 (1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些 ...
- java并发线程池---了解ThreadPoolExecutor就够了
总结:线程池的特点是,在线程的数量=corePoolSize后,仅任务队列满了之后,才会从任务队列中取出一个任务,然后构造一个新的线程,循环往复直到线程数量达到maximumPoolSize执行拒绝策 ...
随机推荐
- 使用Zabbix服务端本地邮箱账号发送报警邮件及指定报警邮件操作记录
邮件报警有两种情况:1)Zabbix服务端只是单纯的发送报警邮件到指定邮箱,发送报警邮件的这个邮箱账号是Zabbix服务端的本地邮箱账号(例如:root@localhost.localdomain), ...
- 常用rsync命令操作梳理
作为一个运维工程师,经常可能会面对几十台.几百台甚至上千台服务器,除了批量操作外,环境同步.数据同步也是必不可少的技能.说到“同步”,不得不提的利器就是rsync.rsync不但可以在本机进行文件同步 ...
- Mysql抓包工具 - MySQL Sniffer 使用小结 (含带general_log日志)
在mysql运维工作中,一般会使用tcpdump做一些分析(直接读分析日志比较难以看明白,在数据库连接值高时使用):对于mysql实时的连接监控分析,通常会使用"mysqladmin/sho ...
- 如何解决jersey框架中以json格式返回数组,当数组中元素一个时json格式不对
原文地址:http://www.cnblogs.com/swpk/p/3566536.html?utm_source=tuicool jersey 是oracle 出的一个较好的REST框架.使用此框 ...
- HTTP协议冷知识大全
如果不用HTTPS,HTTP协议如何安全的传输密码信息? HTTP协议是纯文本协议,没有任何加密措施.通过HTTP协议传输的数据都可以在网络上被完全监听.如果用户登陆时将用户名和密码直接明文通过HTT ...
- 《Linux内核设计与实现》读书笔记 3
第三章 进程管理 3.1进程 概念: 进程:处于执行期的程序.但不仅局限于程序,还包含其他资源(打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内催音社的内存地址空间及一个或多个执行线 ...
- 我的github地址
链接:https://github.com/long0123/test.git 推送项目的github的大致步骤如下: 1.在本地创建一个项目仓库,可以放些基本的项目文件 2.cd至该目录下 3. ...
- spring播放器详细设计说明书(一)
1 引言 1.1编写目的 编写目的是详细说明SPRING音乐播放器的设计使用,预期读者对象为在个人电脑上需要使用简单音乐播放器的用户.1.2项目背景 说明: a.待开发软件系统的名称为SPRING音 ...
- MyEclipse项目里面出现红叉的解决方案?
一般出现在从别处import的项目上,只有项目文件夹上有红叉,其他地方都正常,现总结个人的几个解决方案: 有几种可能: 1,编码设置是否一致,也即是你项目原来的编码和现在eclipse用的默认编码 ...
- 开源通用爬虫框架YayCrawler-开篇
各位好!从今天起,我将用几个篇幅的文字向大家介绍一下我的一个开源作品--YayCrawler,其在GitHub上的网址是:https://github.com/liushuishang/YayCraw ...