Executor框架

Executor类:在java.util.concurrent类中,是JDK并发包的核心类。

ThreadPoolExecutor: 线程池。

Excutors: 线程池工厂,通过Executor可以创建一个特定功能的线程池。

一)、Executor框架的类的关系

Executor, ExecutorService, AbstractExcutorService, ThreadPoolExecutor,Executors

Eecutor类:

接口,只有一个execute()方法:

public interface Executor {
void execute(Runnable command);
}

ExecutorService extends Executor类:

接口,ExecutorService extends Executor,主要方法如下:

   //关闭线程池
void shutdown();
boolean isShutdown();
List<Runnable> shutdownNow();
boolean isTerminated();
<T> Future<T> submit(Callable<T> task);
//提交线程任务,并返回执行结果
Future<?> submit(Runnable task);

AbstractExecutorService类:

abstract class AbstractExecutorService implements ExecutorService,主要实现submit()方法。

    public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
//内部还是调用了execute()
execute(ftask);
return ftask;
}

ThreadPoolExecutor类:

class ThreadPoolExecutor extends AbstractExecutorService

二)、线程池的状态:

参考:https://blog.csdn.net/nobody_1/article/details/98335594

运行(RUNNING): 线程池接收新任务,并处理队列中的任务。

关机(SHUTDOWN): 线程池不接受新的任务,但接收队列的任务,调用

​ shutdown()后线程的状态。

停止(STOP): 线程池不接受新的任务,也不处理队列中的任务,并中断执行中

​ 的任务,调用shutdownNow()线程的状态。

清理(tidying): 线程池所有任务已经终止,workCount(当前线程个数)为0,过渡

​ 到清理状态的线程将运行terminated()的子方法 。

终止(terminated): terminate()方法结束后线程的状态。

    //线程池的容量11111111111111111111111111111: 29个1
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//运行状态,-2^29,10000000000000000000000000000,1个1,29个0
private static final int RUNNING = -1 << COUNT_BITS; // 关机状态 0
private static final int SHUTDOWN = 0 << COUNT_BITS;
// 停止 2^29
private static final int STOP = 1 << COUNT_BITS;
// 清理状态 2 * 2^29
private static final int TIDYING = 2 << COUNT_BITS;
// 终止状态 3 * 2^29
private static final int TERMINATED = 3 << COUNT_BITS;

注:使用线程的高三位代表线程的状态,使用低29位代表工作线程的个数。

三)、获取池状态

private static int runStateOf(int c){
//获得高3位
return c & ~ CAPACITY;
}

四)、获得工作线程数

private static int workerCountOf(int c){
return c & Capacity;
}

五)、使用AtomicInteger变量来表示线程池状态和工作线程数量

//刚开始初始化时,线程的状态默认为RUNNING, 工作线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)) //rs:运行状态(runState), wc:工作线程数 (workCount)
private static int ctlOf(int rs, int wc) {
return rs | wc;
}

使用ctl可以获取线程状态和工作线程数

int c = ctl.get();

runStateOf(c): 获取运行状态

workerCountOf(c): 获取工作线程数

六)、线程池对象:ThreadPoolExecutor

1)、主要属性:


//线程池的锁
private final ReentrantLock mainLock = new ReentrantLock(); //线程池中重用线程对象
private final HashSet<Worker> workers = new HashSet<Worker>(); //最大线程个数
private int largestPoolSize;
//当线程超过最大核心线程数时的阻塞队列
private final BlockingQueue<Runnable> workQueue; //实时监控线程池的状态和工作线程的个数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程池的容量
private static final int CAPACITY = (1 << COUNT_BITS) - 1; //线程池的运行状态
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;

2)、构造方法:

    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;
}

3)、参数信息:

corePoolSize: 指定了线程池中的线程数量

maximumPoolSize: 指定线程池中的最大线程数量

KeepAliveTime: 超过corePoolSize后增加的线程的空闲时间,超过这个时间线程

​ 未使用,则销毁该线程。

unit: KeepAliveTime的单位

workQueue: 任务队列,被提交但尚未被执行的任务

threadFactory: 线程工厂,一般用于创建线程。

handle: 拒绝策略,当任务太多,来不及处理,如何拒绝任务。

七)、workeQueue:等待队列

1).SynchronousQueue:直接提交的队列

​ 特点: 没有容量,每一个插入操作都要等待一个相应的删除操作。

​ 作用:应用于new CacheThreadPool线程池的workerQueue队列,不保存任务,

​ 总 是将任务提交给线程执行,如果没有空闲的进程,则尝试创建新的线

​ 程,如果进程的数量达到最大值,则执行拒绝策略。

注: 一直创建新的线程,直至线程数到达maximumPoolSize,执行拒绝策略。

2).ArrayBlockingQueue: 有界队列

​ 特点:使用构造函数,指定队列的最大容量

public ArrayBlockingQueue(int capacity){

}

​ 作用:当有新的任务要执行时,如果线程池的实际线程数小于coreSize,则会优先

​ 创建新的线程,若大于corePoolSize,则会将新任务加入等待队列,若等

​ 待队已满,在总线程数不大于maximumPoolSize的前提下创建线程,当总

​ 线程 数超过maxmmumPoolSize时执行拒绝策略。

** 注:**当线程数小于coreSize时,创建新的线程,大于coreSize时,将任务加入

​ 等待 队列,直至等待队列加满,在总线程数不超过maximumPoolSize的前

​ 提下创建线程,否则,执行拒绝策略。

3).LinkedBlockingQueue: 无界队列

​ 特点:除非资源耗尽,否则无界队列不存在任务入队失败的情况。

​ 作用:系统有任务时,若总的线程数小于corePoolSize则创建新的线程,否则,

​ 则将线程添加至等待队列中,无界队列保持快速增长,直至耗尽系统内

​ 存。

​ ** 注:** 当线程数小于corePoolSize时,创建新的线程,大于corePoolSize时,将

​ 任务加入等待队列中,直至耗尽系统内存,线程的个数一直维护在

​ corePoolSize 。

4).PriorityBlockingQueue: 优先任务队列

​ 特点:控制任务的执行先后顺序,是一个特殊的无界队列

作用:根据任务自身的优先级先后执行

八)、handler,JDK内置的四种拒绝策略

1). AbortPolicy: 直接抛出异常,阻滞系统工作

2).CallerRunsPolicy: 在调用者线程中运行当前被丢弃任务

3).DiscardOledstPolicy: 丢弃最老的一个请求,即即将被执行的一个任务,并尝试

​ 再次提交当前任务。

4).DiscardPolicy: 丢弃无法处理的任务,不予任何处理。

注:若要自定义拒绝策略,实现RejecteExecutionHandler接口,实现

​ rejectedExecution方法。

九)、execute()方法

步骤:

1)、参数传递,得到一个任务对象

2)、判断

//Runnable command 当前要执行的线程任务
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//获取定前线程池的状态
int c = ctl.get();
//判断当前主线程数量是否超过corePoolSize,如果不超过,则新建一个线程对象
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//将任务添加到等待队列中,若队列未满,添加。已满,执行拒绝策略
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//队列已满,执行拒绝策略回调
else if (!addWorker(command, false))
reject(command);
} //线程池中添加新的线程,并执行线程任务
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
//获取运行状态
int rs = runStateOf(c); // Check if queue empty only if necessary.
//如若当前处于关闭、清理、终止,任务队列不为空时返回false,因为,队列不为空,说明线程个数达到核心线程的个数,不能创建新的线程值,返回false
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false; for (;;) {
//获取当前的主线程数
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//增加线程池的大小
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
} boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//重新创建一个线程
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//线程池中添加新线程
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//执行线程任务
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}

七)、Executors:线程池工厂

继承ThreadPoolExecutor,可以取得一个特定功能的线程池

构造方法:

注:所有的线程池的构造,其内部最终都是调用了ThreadPoolExecutor的构造方法

1)、newFixThreadPool(int nThread): 创建一个固定大小的线程池

 public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

2)、newSingleThreadExecutor(): 返回一个只有一个线程的线程池

    public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
  1. 、new CacheThreadPool(): 返回一个可以根据实际情况调整线程数量的线程池
    public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

4)、new SingleThreadSchaduleExecutor(): 返回一个ScheduleExecutor对象,

retry: 标记循环位置,在continur和break后面加retry表示循环直接跳出到retry标

​ 记处。

   public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}

使用Executor框架创建线程池的更多相关文章

  1. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  2. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  3. 并发新特性—Executor 框架与线程池

    兰亭风雨 · 更新于 2018-11-14 09:00:31 并发新特性-Executor 框架与线程池 Executor 框架简介 在 Java 5 之后,并发编程引入了一堆新的启动.调度和管理线程 ...

  4. java并发编程(十七)Executor框架和线程池

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17465497   Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动 ...

  5. 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

      Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...

  6. 【Java并发编程】:并发新特性—Executor框架与线程池

    Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...

  7. Java的Executor框架和线程池实现原理

    Java的Executor框架 1,Executor接口 public interface Executor { void execute(Runnable command); } Executor接 ...

  8. Java 并发编程中的 Executor 框架与线程池

    Java 5 开始引入 Conccurent 软件包,提供完备的并发能力,对线程池有了更好的支持.其中,Executor 框架是最值得称道的. Executor框架是指java 5中引入的一系列并发库 ...

  9. 并发新特性—Executor框架与线程池

    http://blog.csdn.net/ns_code/article/details/17465497 Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的AP ...

随机推荐

  1. pytest5-使用conftest.py实现多文件共享fixture

    一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用.在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效. ...

  2. dapper之连接数据库(Oracle,SQL Server,MySql)

    因为项目需求,需要项目同时可以访问三个数据库,因此本人经过一番研究,得出以下代码. 1.建立公共连接抽象类(DataBase) public abstract class DataBase { /// ...

  3. 个人记账app(一)需求设计

    时间如流水,只能流去不流回. 学历代表你的过去,能力代表你的现在,学习能力代表你的将来. 学无止境,精益求精. 一.开发背景 Android应用市场记账的app那么多,我为什么还要再开发一个呢?重复造 ...

  4. next day

    #_*_coding:utf_*_#!/usr/bin/env python now_day=input('当前某一天:').format('%Y.%m.%d')%%输入日期(年.月.日) year= ...

  5. MacOs mysql 安装

    1. 去官网下载mysql镜像:https://dev.mysql.com/downloads/file/?id=475582 2.  双击镜像文件 - >  双击.pkg文件 -> 出现 ...

  6. Dubbo学习系列之十六(ELK海量日志分析框架)

    外卖公司如何匹配骑手和订单?淘宝如何进行商品推荐?或者读者兴趣匹配?还有海量数据存储搜索.实时日志分析.应用程序监控等场景,Elasticsearch或许可以提供一些思路,作为业界最具影响力的海量搜索 ...

  7. ArcGIS Engine空间分析之缓冲区分析的实现

    缓冲分析(BufferAnalysis)的结果是一个面状要素——即缓冲要素,点状要素.线状要素和面状要素,被缓冲分析功能处理过之后,它们的周围产生一个缓冲区域,该区域即新产生的面状要素. 在缓冲方向上 ...

  8. phpstorm 2016.2.2 激活

    2016年7月14日 phpstorm 推送2016.2 更新 2016年10月25日phpstorm 推送2016.2.2 更新 2016年11月24日phpstorm 推送2016.3 更新 下面 ...

  9. [知识图谱]利用py2neo从Neo4j数据库获取数据

    # -*- coding: utf-8 -*- from py2neo import Graph import json import re class Neo4jToJson(object): &q ...

  10. java.io.StreamCorruptedException: invalid stream header: 00000000

    Caused by: java.io.StreamCorruptedException: invalid stream header: 00000000 at java.io.ObjectInputS ...