JUC - ThreadPoolExecutor

创建一个ThreadPoolExecutor

ThreadPoolExecutor(
int corePoolSize, // 保留在池中的线程数,即使空闲了也保留(除非设置了{@code allowCoreThreadTimeOut})
int maximumPoolSize, // 池中允许的最大线程数
long keepAliveTime, // 当maximumPoolSize>corePoolSize时,多余空闲线程等待任务的时间
TimeUnit unit, // {@code keepAliveTime}参数的时间单位
BlockingQueue<Runnable> workQueue, // 在task执行之前暂存task.队列只接纳被 {@code execute}方法提交的{@code Runnable}task
ThreadFactory threadFactory, // 创建执行task线程的工厂
RejectedExecutionHandler handler // 如果达到线程界限或者队列容量,拒绝任务执行的处理
)

参数限制

  • 满足以下条件之一则抛出IllegalArgumentException

    • corePoolSize < 0
    • keepAliveTime < 0
    • maximumPoolSize <= 0
    • maximumPoolSize < corePoolSize
  • 抛出NullPointerException
    • threadFactory == null
    • handler == null

参数补充说明

  • corePoolSize : 如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过corePoolSize,则新建的是非核心线程
  • keepAliveTime : 指该线程池中非核心线程闲置超时时长, 超过这个参数所设定的时长,就会被销毁掉, 如果设置allowCoreThreadTimeOut = true,则会作用于核心线程
  • unit : TimeUnit时间
  • maximumPoolSize : 线程总数 = 核心线程数 + 非核心线程数
  • workQueue : 当核心线程都在工作时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务
    • ArrayBlockingQueue : 构造函数一定要传大小
    • LinkedBlockingQueue : 构造函数不传大小会默认为Integer.MAX_VALUE,当大量请求任务时,容易造成内存耗尽.由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
    • SynchronousQueue : 同步队列,一个没有存储空间的阻塞队列 ,将任务同步交付给工作线程.此队列通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务
    • PriorityBlockingQueue : 优先队列
    • DelayQueue : 传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
  • threadFactory : 线程工厂(默认值Executors.defaultThreadFactory())
  • handler : 拒绝策略
    • AbortPolicy(默认) : 直接抛弃
    • CallerRunsPolicy : 拒绝这个任务,不在ThreadPoolExecutor线程池中的线程中运行,而是调用当前线程池的所在的线程去执行被拒绝的任务
    • DiscardOldestPolicy : 抛弃队列中最久的任务(最先加入队列的任务),再把这个新任务添加到队列中去。
    • DiscardPolicy : 线程池默默丢弃这个被拒绝的任务,不会抛出异常。

执行过程

  • 1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
  • 2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
  • 3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
  • 4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
  • 5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
  • 6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

Executors中常见的ThreadPoolExecutor

  • 单个线程池: Executors.newSingleThreadExecutor() || Executors.newSingleThreadExecutor(ThreadFactory threadFactory)

    • new ThreadPoolExecutor(1, 1,

      0L, TimeUnit.MILLISECONDS,

      new LinkedBlockingQueue())
    • new ThreadPoolExecutor(1, 1,

      0L, TimeUnit.MILLISECONDS,

      new LinkedBlockingQueue(),

      threadFactory)
    • 创建单个线程
  • 固定线程池: Executors.newFixedThreadPool(int nThreads) || Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
    • new ThreadPoolExecutor(nThreads, nThreads,

      0L, TimeUnit.MILLISECONDS,

      new LinkedBlockingQueue())
    • new ThreadPoolExecutor(nThreads, nThreads,

      0L, TimeUnit.MILLISECONDS,

      new LinkedBlockingQueue(),

      threadFactory);
    • 核心线程和最大线程相同,并且不过期
  • 缓存线程池: Executors.newCachedThreadPool() || Executors.newCachedThreadPool(ThreadFactory threadFactory)
    • new ThreadPoolExecutor(0, Integer.MAX_VALUE,

      60L, TimeUnit.SECONDS,

      new SynchronousQueue())
    • new ThreadPoolExecutor(0, Integer.MAX_VALUE,

      60L, TimeUnit.SECONDS,

      new SynchronousQueue(),

      threadFactory)
    • 核心线程为0,并且阻塞队列为SynchronousQueue,按需创建线程,默认过期时间60s
  • 调度线程池: Executors.newScheduledThreadPool(int corePoolSize) || Executors.newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
    • new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE,

      0, TimeUnit.NANOSECONDS,

      new DelayedWorkQueue())
    • new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE,

      0, TimeUnit.NANOSECONDS,

      new DelayedWorkQueue(),

      threadFactory)
    • 可以调度命令以在给定延迟后运行或定期执行
  • 窃取线程池: Executors.newWorkStealingPool() || Executors.newWorkStealingPool(int parallelism)
    • new ForkJoinPool

      (Runtime.getRuntime().availableProcessors(),

      ForkJoinPool.defaultForkJoinWorkerThreadFactory,

      null, true);
    • new ForkJoinPool

      (parallelism,

      ForkJoinPool.defaultForkJoinWorkerThreadFactory,

      null, true)
    • 窃取线程是ForkJoinPool的拓展(分治算法),创建一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行,适合很耗时间的任务

参考阅读

JUC - ThreadPoolExecutor的更多相关文章

  1. 【JUC】JDK1.8源码分析之ThreadPoolExecutor(一)

    一.前言 JUC这部分还有线程池这一块没有分析,需要抓紧时间分析,下面开始ThreadPoolExecutor,其是线程池的基础,分析完了这个类会简化之后的分析,线程池可以解决两个不同问题:由于减少了 ...

  2. JUC 之 ThreadPoolExecutor 的一些研究

    ThreadPoolExecutor 概述:===================================================================== 构造函数: 4个 ...

  3. Java - "JUC线程池" ThreadPoolExecutor原理解析

    Java多线程系列--“JUC线程池”02之 线程池原理(一) ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存 ...

  4. juc线程池原理(二):ThreadPoolExecutor的成员变量介绍

    概要 线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析ThreadPoolExecutor类,来了解线程池的原理. ThreadPoolExecutor数据结构 Thread ...

  5. JUC - Monitor监控ThreadPoolExecutor

    JUC - Monitor监控ThreadPoolExecutor 一个自定义Monitor监控ThreadPoolExecutor的执行情况 TASK WokerTask class WorkerT ...

  6. JUC源码分析-线程池篇(一):ThreadPoolExecutor

    JUC源码分析-线程池篇(一):ThreadPoolExecutor Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池 ...

  7. 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

    前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...

  8. JUC回顾之-ThreadPoolExecutor的原理和使用

    Spring中的ThreadPoolTaskExecutor是借助于JDK并发包中的java.util.concurrent.ThreadPoolExecutor来实现的.基于ThreadPoolEx ...

  9. JUC线程池之 ThreadPoolExecutor简介

    ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合.线程池允许若个线程同时允许,允许同 ...

随机推荐

  1. 破解NFC卡

    目录 概念 各种卡 IC卡存储器结构 破解工具 破解NFC卡 概念 各种卡 ID卡 工作在低频(125Khz) ID卡 特点 EM4XX系列,多为EM4100/EM4102卡 常用的固化ID卡,出厂固 ...

  2. H3C交换机恢复出厂设置

    reset saved-configuration reboot 恢复出厂设置后查看当前配置: ..............................

  3. NodeJs FS 文件系统模块

    1. fs.stat 检测是文件还是目录 fs.stat('html',function(err,stats){ if(err){ console.log(err); return false; } ...

  4. GBDT学习笔记

    GBDT(Gradient Boosting Decision Tree,Friedman,1999)算法自提出以来,在各个领域广泛使用.从名字里可以看到,该算法主要涉及了三类知识,Gradient梯 ...

  5. .netcore里使用StackExchange.Redis TimeOut 情况解决方法

    在用StackExchange.Redis这个组件时候,时不时会出现异常TimeOut解决方法如下, 解决方法: 在Program的Main入口方法里添加一句话: System.Threading.T ...

  6. MongoDB开发深入之二:索引

    索引分类: 默认索引 单一索引 复合索引 多键索引(数组索引) 全文检索索引 2dsphere 索引 2D索引 ...... 索引属性: 到期TTL 唯一索引 部分索引 稀疏索引 索引通常能够极大的提 ...

  7. Laya的List组件+滚动条

    版本:2.2.0 下面以<绯雨骑士团>的服务器选择列表为例子. 一 创建List 首先创建一个List组件,我命名为serverList. (不用像laya教程里那样,还要转换类型什么的, ...

  8. The 10 Best Studio Headphones of 2019

    The 10 Best Studio Headphones of 2019 https://www.outeraudio.com/category/list/ https://www.outeraud ...

  9. 【C/C++开发】C++11:左值引用VS右值引用

    左值引用VS右值引用 左值引用对于一般的C++程序员再熟悉不过,但对于右值引用(C++0X新特性),就稍微有点不知所云 左值VS右值 在定义变量的时候,经常会用到左值和右值,比如:int a = 1; ...

  10. [QT] - 图片查看器(数码相框)#工程源码

    简介: 大学期间弄的一个小软件,当时是将该软件移植到嵌入式开发板使用的,软件的几个功能截图如正文所示,文末提供工程源码文件,感谢支持! 功能截图: [ 打开软件 ] [ 打开图片 ] [ 图片可放大. ...