java.util.concurrent

public class ThreadPoolExecutor extends AbstractExecutorService

ThreadPoolExecutor实现类

三种ThreadPoolExecutor实现类:

ExecutorService newCachedThreadPool():
无界线程池,如果有可用线程,当线程池调用execute, 将重用之前的构造函数。
如果没有现有的线程可用,那么就创建新的线程并添加到池中。
核心线程数为0,最大线程数为Integer最大值大小,超过0个的空闲线程在60秒后销毁 ExecutorService newFixedThreadPool():
有界线程池,可控制线程最大并发数,超出的线程会在队列中等待。
核心线程数和最大线程数固定相等 ExecutorService newSingleThreadExecutor():
单线程线程池,核心线程数和最大线程数均为1
每次只执行一个线程,多余的先存储到工作队列,一个一个执行,保证了线程的顺序执行。 三种线程池的构造函数: public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
} 四种ThreadPoolExecutor构造函数: public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) int corePoolSize:
核心线程数,即使空闲也仍保留在池中的线程数 int maximumPoolSize:
最大线程数(线程总数计算公式 = 核心线程数 + 非核心线程数) BlockingQueue<Runnable> workQueue:
阻塞队列,在执行任务之前用于保存任务的队列维护着等待执行的Runnable对象。
当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务 long keepAliveTime:
保持激活时间,当线程数大于核心数时,这是多余的空闲线程在终止之前等待新任务的最大时间 TimeUnit unit:
keepAliveTime的时间单位 threadFactory:
线程工厂,主要用来创建线程 handler:
表示当拒绝处理任务时的策略

执行过程

  1. 如果线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
  2. 如果线程数量达到了corePools,则将任务移入队列等待
  3. 如果队列已满,新建线程(非核心线程)执行任务
  4. 如果队列已满,总线程数又达到了maximumPoolSize,就会由RejectedExecutionHandler抛出异常

拒绝策略(超过最大线程数时)

当线程池已经关闭或达到饱和(最大线程和队列都已满)状态时,新提交的任务将会被拒绝。

handler:表示当拒绝处理任务时的策略,有以下四种取值:

  1. AbortPolicy

    简单粗暴,直接抛出拒绝异常,这也是默认的拒绝策略。
  2. CallerRunsPolicy

    如果线程池未关闭,则会在调用者线程中直接执行新任务,这会导致主线程提交线程性能变慢。
  3. DiscardPolicy

    从方法看没做任务操作,即表示不处理新任务,即丢弃。
  4. DiscardOldestPolicy

    抛弃最老的任务,就是从队列取出最老的任务然后放入新的任务进行执行。

任务缓存队列及排队策略

workQueue,它用来存放等待执行的任务。

workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

  1. ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
  2. LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
  3. synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

提交线程

ExecutorService接口继承了Executor接口,并声明了一些方法:submitinvokeAllinvokeAny以及shutDown

AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法

ThreadPoolExecutor继承了类AbstractExecutorService

ThreadPoolExecutor类中有几个非常重要的方法:execute()submit()shutdown()shutdownNow()

ExecutorService es = Executors.newFixedThreadPool(3);

提交一个线程:

  1. es.execute(Runnble run);
  2. es.submit(Runnble run);

submit和execute分别有什么区别:

  1. execute没有返回值,如果不需要知道线程的结果就使用execute方法,性能会好很多。
  2. submit返回一个Future对象,如果想知道线程结果就使用submit提交。

关闭线程池:

  1. es.shutdown(); (不能够接受新的任务,它会等待所有任务执行完毕)
  2. es.shutdownNow();(不能接受新的任务,也不会运行队列任务,并且会去尝试终止正在执行的任务)此方法并不能保证一定会停止每个任务。

线程池容量的动态调整

ThreadPoolExecutor提供了动态调整线程池容量大小的方法:setCorePoolSize()setMaximumPoolSize()

setCorePoolSize:设置核心池大小

setMaximumPoolSize:设置线程池最大能创建的线程数目大小

线程池状态

ThreadPoolExecutor封装了两个概念字段:

workerCount:表示工作线程数,最大为(2^29)-1

runState:提供了对池生命周期的控制,包括以下几种状态:

  1. RUNNING:可以接收新的任务和队列任务
  2. SHUTDOWN:不接收新的任务,但是会运行队列任务
  3. STOP:不接收新任务,也不会运行队列任务,并且中断正在运行的任务
  4. TIDYING:所有任务都已经终止,workerCount为0,当池状态为TIDYING时将会运行terminated()方法
  5. TERMINATED:terminated()函数完成执行。

转换:

线程池 一 ThreadPoolExecutor的更多相关文章

  1. 从源码解读线程(Thread)和线程池(ThreadPoolExecutor)的状态

    线程是比进程更加轻量级的调度执行单位,理解线程是理解并发编程的不可或缺的一部分:而生产过程中不可能永远使用裸线程,需要线程池技术,线程池是管理和调度线程的资源池.因为前不久遇到了一个关于线程状态的问题 ...

  2. Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析

    目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...

  3. 线程池之 ThreadPoolExecutor

    线程池之 ThreadPoolExecutor + 面试题 线程池介绍 线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销. ...

  4. 高并发之——不得不说的线程池与ThreadPoolExecutor类浅析

    一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但为什么在JDK1.5中又提供了线程池技术呢?这个问题大家自行脑补,多动脑,肯定没坏处,哈哈哈... 说起Java中的线程池技术,在很多 ...

  5. 【高并发】不得不说的线程池与ThreadPoolExecutor类浅析

    大家好,我是冰河~~ 今天,我们一起来简单聊聊线程池中的ThreadPoolExecutor类,好了,不多说了,开始进入今天的正题. 一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但 ...

  6. 线程池:ThreadPoolExecutor

    [ThreadPoolExecutor的使用和思考]   public ThreadPoolExecutor(int corePoolSize,                             ...

  7. Java线程池之ThreadPoolExecutor

    前言 线程池可以提高程序的并发性能(当然是合适的情况下),因为对于没有线程的情况下,我们每一次提交任务都新建一个线程,这种方法存在不少缺陷: 1.  线程的创建和销毁的开销非常高,线程的创建需要时间, ...

  8. 从源码看JDK提供的线程池(ThreadPoolExecutor)

    一丶什么是线程池 (1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些 ...

  9. java并发线程池---了解ThreadPoolExecutor就够了

    总结:线程池的特点是,在线程的数量=corePoolSize后,仅任务队列满了之后,才会从任务队列中取出一个任务,然后构造一个新的线程,循环往复直到线程数量达到maximumPoolSize执行拒绝策 ...

随机推荐

  1. linux 7 安装KVM

    首先,在安装GUI的linux 7系统下,安装KVM 执行命令 #yum install qemu-kvm qemu-kvm-tools virt-manager libvirt virt-insta ...

  2. 笔记65 Spring Boot快速入门(五)

    SpringBoot+JPA 一.什么是JPA? JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期 ...

  3. 理解 Java 序列化

    一.什么是序列化 序列化是一种对象持久化的手段.类通过实现 java.io.Serializable 接口以启用其序列化功能. 序列化:把对象转换为字节序列的过程. 反序列化:把字节序列恢复为对象的过 ...

  4. 每天一个Linux命令:mkdir(4)

    mkdir mkdir命令 用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录 格式 mkdir [选项] [目录..] 参数选项 参数 备 ...

  5. NOIP模拟测试19

    T1: 题目大意:将一颗有N个节点的树分割,使得每个联通块大小相等,问一共有多少方案.(N<=1000000) 首先,一条很显然的性质,每个联通块的大小一定是N的因子. 然后,我们可以对于每个因 ...

  6. 基础(二):Linux系统/etc/init.d目录和/etc/rc.local脚本

    原文来自http://www.ghacks.net/2009/04/04/get-to-know-linux-the-etcinitd-directory/ 译文来自http://blog.csdn. ...

  7. BZOJ 4516: [Sdoi2016]生成魔咒(后缀数组)

    传送门 解题思路 题目其实就是动态维护本质不同的串的个数.考虑到只有加数字的操作,所以可以用后缀数组.题目是每次往后加数字,这样不好处理,因为每次加数字之后所有的后缀都会改变.所以要转化一下思路,就是 ...

  8. 文件上传 和 base64编码

    base64编码 1.关于Base64编码  :  https://www.cnblogs.com/liyiwen/p/3814968.html (个人猜测),file表单发送文件,肯定是将文件转换为 ...

  9. 【前端技术】一篇文章搞掂:CSS

    Flex布局 Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性. /*父容器,设置弹性布局*/ .parent{display: flex;} /*设置父容器主轴方向* ...

  10. mysql笔试题大餐---1、组合查询方式及having

    mysql笔试题大餐---1.组合查询方式及having 一.总结 一句话总结: 实践:我之前的mysql真的学的太浅了,这种情况下,依据实践(做题)才是唯一能把它学好的方式 学的暂时够了,以实践而学 ...