线程池之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执行拒绝策 ...
随机推荐
- C. Books Queries
链接 [http://codeforces.com/contest/1066/problem/C] 题意 开始空队列,可以进行前插和后插,还可以查询使某个数的为最左或最右需要去掉的最少数字 分析 模拟 ...
- M1阶段个人总结
经过4周的开发,我们团队的第一阶段已经结束了. 这一个月来我由于其他事情较多,所以开发的工作主要交给了另外的三名同学. 我主要负责制定代码规范和工程结构,通过github来跟进项目进度,提供一些技术支 ...
- Linux期末总结
Linux内核学习总结 1.计算机是如何工作的? 存储程序计算机工作模型 X86汇编基础 汇编一个简单的C程序分析其汇编指令执行过程 2.操作系统是如何工作的? 三个法宝——存储程序计算机.函数调用堆 ...
- nginx+tpmcat+redis实现session共享
nginx+tpmcat+redis实现session共享 版本:nginx nginx-1.8.0.tar.gztomcat apache-tomcat-7.0.78.tar.gzredis re ...
- shell脚本--制作自己的服务脚本
首先注意一下,我用的环境是centos6.5,中间有一些操作和在Ubuntu上有一些地方的操作是不同的, 编写脚本 首先看一个实例:假设有一个test的服务,可以通过命令对test进行启动.关闭或者重 ...
- DispatcherServlet源码分析
一.客户端发送请求的总体过程 DispatcherServlet是SpringMVC的入口,DispatcherServlet其实也是一个Servlet.服务器处理客户端请求的步骤如下: 1.客户端发 ...
- python学习笔记三——控制语句
2.5 运算符与表达式 2.5.1 算术运算符和算术表达式 算术运算符包括四则运算符.求模运算符和求幂运算符. 算术运算符 加减乘除:+ - * / 表达式:x+y x-y x*y x/y ...
- js 錯誤
try{ //需要被檢測是否拋出錯誤 } catch(err) { //錯誤處理代碼 } try.catch成對出現 throw:拋出錯誤 當錯誤發生時,javascript引擎停止運行,并生成一個錯 ...
- Maven环境配置及简单使用(二)
Maven环境变量配置 配置Maven前先从官网下载相关版本,Maven下载地址:http://maven.apache.org/download.cgi,笔者使用最新版本apache-maven-3 ...
- LOJ116 有源汇有上下界最大流(上下界网络流)
考虑有源汇上下界可行流:由汇向源连inf边,那么变成无源汇图,按上题做法跑出可行流.此时该inf边的流量即为原图中该可行流的流量.因为可以假装把加上去的那些边的流量放回原图. 此时再从原来的源向原来的 ...