线程池基础知识

ThreadPoolExecutor : 一个线程池

Executors : 线程池工厂,通过该类可以取得一个拥有特定功能的线程池

ThreadPoolExecutor类实现了Executor接口,因此通过这个接口,任何的Runnable对象都可以被ThreadPoolExecutor线程池调度。

常见的线程池类型

  • public static ExecutorService newFixedThreadPool(int nThreads)

    返回一个固定线程数量的线程池。线程数量始终不变。当有空闲线程时,立即执行;若没有,新线程暂存在一个任务队列中,待线程空闲,便开始处理任务队列中的任务。

  • public static ExecutorService newSingleThreadExecutor()

    返回一个只有一个线程的线程池。新线程过来存放在任务队列中,线程空闲时,处理任务队列中的任务。

  • public static ExecutorService newCachedThreadPool()

    返回一个可以根据实际情况调整线程数量的线程池。线程的进程数不确定,但是如果有空闲线程可以复用,则会优先使用该线程。如果所有线程都在工作,又有新的任务提交,那么就会创建新的线程执行任务。所有线程在当前任务完成之后,将返回线程池进行服用。

  • public static ScheduledExecutorService newSingleThreadScheduldExecutor()

    返回一个ScheduledExecutorService对象,线程池大小为1。在某个固定的延时之后执行,或者周期性执行某个任务

  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

    和上面一样,但是可以指定线程数。


核心线程池的内部实现

对于核心的几个线程池,其内部实现都是使用了ThreadPoolExecutor实现。

  • public static ExecutorService newFixedThreaPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads,nThreads,
    0L,TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());
    }
  • public static ExecutorService newSingleThreadExecutor() {
    return new ThreadPoolExecutor(1,1,
    0L,TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());
    }
  • public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0,Integer.MAX_VALUE,
    60L,TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>());
    }

看一下ThreadPoolExecutor最重要的构造函数

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long KeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

函数的参数含义如下:

  • corePoolSize:线程池中的线程数量。
  • maximumPoolSize:线程池中的最大线程数量。
  • keepAliveTime:当线程池数量超过corePoolSize时,多余的空闲线程的存活时间。
  • unitkeepAliveTime的单位。
  • workQueue:任务队列,被提交但是尚未被执行的任务。
  • threadFactory:线程工厂,用于创建线程,一般用默认的就行。
  • handler:拒绝策略。当任务太多来不及处理,如何拒绝任务。

在上面的参数中,其他的都好理解,主要是workQueuehandler需要重点提及一下。


workQueue 任务队列讲解

workQueue 指被提交但是尚未被执行的任务队列,它是一个BlockingQueue接口的对象,仅用于存在Runnable对象。根据队列功能分类,在ThreadPoolExecutor的构造函数中可以使用以下几种BlockingQueue

  • 直接提交的队列SynchronousQueueSychronousQueue是一个特殊的BlockingQueueSychronousQueue没有容量,每一个插入操作都要等待一个相应的删除操作,反之,一个删除操作都要等待对应的插入操作。如果使用SychronousQueue,提交的任务不会被真实的保存,而总是将新任务提交给线程执行,如果没有空闲线程,那么尝试创建新的线程,如果进程数量已经达到最大值,则执行拒绝策略。因此,使用SychronousQueue通常要设置很大的maximumcorePoolSize,否则很容易执行拒绝策略。
  • 有界的任务队列ArrayBlockingQueue:特点:若有新的任务需要执行,如果线程池的实际线程小于corePoolSize,则会优先创建新的线程;若大于corePoolSize,则会将新任务加入到等待队列。如果等待队列已满,无法加入,则在总线成熟不大于maximumPoolSize的前提下,创建新的线程执行任务。若大于,则执行拒绝策略。
  • 无界的任务队列LinkedBlockingQueue:特点:若有新的任务需要执行,如果线程池的实际线程小于corePoolSize,则会优先创建新的线程;若大于corePoolSize,进入等待队列。
  • 优先任务队列PriorityBlockingQueue:可以根据任务自身的优先级顺序先后执行。

handler拒绝策略讲解

JKD 内置的拒绝策略都是通过实现RejectedExecutionHandler接口实现的,具体如下:

  • AbortPolicy策略:直接抛出异常,阻止系统正常工作;
  • CallerRunsPolicy策略:只要线程未关闭,直接在调用者线程中,运行当前被丢弃的任务。warning:有可能性能会急剧下降
  • DiscardOledstPolicy策略:丢弃一个最老的请求,并尝试再次提交当前的任务。
  • DiscardPolicy策略:丢弃无法处理的请求,不予任何处理,不做出任何的提示。

Java 线程池 ThreadPoolExecutor 的那些事儿的更多相关文章

  1. Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  2. Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  3. Java线程池ThreadPoolExecutor使用和分析(一)

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  4. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  5. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  6. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  7. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

  8. Java线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  9. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue

    从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构 ...

随机推荐

  1. python交互界面无法使用方向键

    问题 python交互界面无法使用方向键,按方向键全变成^[[^C这类型的字符 解决办法 办法1: 使用yum安装readline.readline-devel,然后重装python 这种方法太麻烦了 ...

  2. Unittest 支持 case 失败后自动截图功能的另外两种方式

    原生的unittest框架是不支持case失败后自动截图的功能的,网上看了大家的解决办法,大体上分为两种:1.要么加装饰器2.也有人封装断言这里我们看看还有没有其他的更加方便的方法值得大家一起探讨一下 ...

  3. ceph 初始化函数解析

    global_pre_init 预初始化函数,解析ceph.conf配置文件, 初始化定义global_context 和 config的全局变量. 全局预初始化函数 CINIT_FLAG_UNPRI ...

  4. 【kafka】一、消息队列

    在高并发的应用场景中,由于来不及同步处理请求,接收到的请求往往会发生阻塞.例如,大量的插入.更新请求同时到达数据库,这会导致行或表被锁住,最后会因为请求堆积过多而触发“连接数过多的异常” 的错误.因此 ...

  5. 通过Powershell修改文件默认打开方式

    修改原理 详情: Windows下通过注册表修改某个类型文件的默认打开方式和文件图标 脚本详情: Github:Change_default_programs.ps1 描述: 至少在Windows10 ...

  6. LR有的JMeter也有之三“集合点”

    继续上两篇的文章内容和思路进行.(文思如尿崩,谁与我争锋----韩寒)哈哈! 集合点:简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念 ...

  7. 【Java例题】2.1复数类

    1.定义复数类,包括实部和虚部变量.构造方法. 加减乘除方法.求绝对值方法和显示实部.虚部值的方法. 然后编写一个主类,在其主方法中通过定义两个复数对象来 显示每一个复数的实部值.虚部值和绝对值, 显 ...

  8. 『开发技术』GPU训练加速原理(附KerasGPU训练技巧)

    0.深入理解GPU训练加速原理 我们都知道用GPU可以加速神经神经网络训练(相较于CPU),具体的速度对比可以参看我之前写的速度对比博文: [深度应用]·主流深度学习硬件速度对比(CPU,GPU,TP ...

  9. CMake入门-02-HelloWorld扩展

    工作环境 系统:macOS Mojave 10.14.6 CMake: Version 3.15.0-rc4 Hello,World! 扩展-同一目录,多个源文件 (1) 新建 hello 目录,创建 ...

  10. (一)c#Winform自定义控件-基类控件

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...