美文网首页
9.线程池-2

9.线程池-2

作者: nieniemin | 来源:发表于2021-08-04 15:32 被阅读0次

一、常见线程池介绍

上一节中线程池使用到了Executors.newSingleThreadExecutor()方法。接下来介绍下常用的线程池。

newSingleThreadExecutor
  • newSingleThreadExecutor():创建一个单线程化的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
newFixedThreadPool
  • newFixedThreadPool(int nThreads):创建一个可重用固定个数的线程池,每提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行
newCachedThreadPool
  • newCachedThreadPool(): 推荐使用。可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务

  • newScheduledThreadPool(int corePoolSize):创建一个定长线程池,支持定时及周期性任务执行。

在性能上newCachedThreadPool>newFixedThreadPool>newSingleThreadExecutor。通过截图可以看到这三个方法都调用了ThreadPoolExecutor的构造方法,在执行Executors.线程池方法时,idea会提示


给我们的解释如下:

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors返回的线程池对象的弊端如下:
1)FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2)CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

因此在使用线程池时,我们也要放弃前面使用Executors类创建线程池,采用ThreadPoolExecutor类来创建线程池。

二、ThreadPoolExecutor构造函数参数介绍

ThreadPoolExecutor构造器共有7个参数:

  • corePoolSize: 核心线程数

  • maximumPoolSize:池中允许的最大线程数

  • keepAliveTime: 超时时间,当线程数大于核心数时,当空闲时间达到keepAliveTime时,线程会被销毁,直到只剩下corePoolSize个线程

  • TimeUnit: 超时时间的单位,秒,毫秒,微秒,纳秒等,与keepAliveTime参数共同决定超时时间。

  • workQueue:表示如果任务数量超过核心池大小,多余的任务添加到阻塞队列中

  • threadFactory:线程工厂

  • handler:线程池对拒绝任务的处理策略

下图简单介绍了核心线程数、最大线程数工作,分析下核心线程数和最大线程数的关系,有助于加深理解:

(1)当提交一个任务时,先判断线程池中当前线程数量是否达到了corePoolSize,若未达到,则新建线程运行此任务,线程池创建一个新线程(worker)执行任务(task)且任务结束后将该线程保留在线程池中,不做销毁处理。除非设置了allowCoreThreadTimeOut=true时,无论线程数多少,那么线程处于空闲状态超过一定时间(keepAliveTime)就会被销毁掉。

(2)如果达到了corePoolSize,判断工作队列(workQueue)是否已满,未满则将新的任务提交到工作队列中

(3)如果workQueue满了,判断线程池中的线程数量是否达到了maximumPoolSize,如果未达到,则新建一个工作线程来执行这个任务,如果达到了则使用饱和策略来处理这个任务。注意: 在线程池中的线程数量超过corePoolSize时,对于右侧的非核心线程数每当有线程的空闲时间超过了keepAliveTime,这个线程就会被终止。直到线程池中线程的数量不大于corePoolSize为止。

线程池工作

workQueue
用来保存等待被执行的任务的阻塞队列,且任务必须实现Runnable接口,阻塞队列如下:

  • ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
  • LinkedBlockingQuene:基于链表结构的无界阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
  • PriorityBlockingQueue:使用平衡二叉树,实现的具有优先级的无界阻塞队列
  • DelayQueue:无界阻塞延迟队列,队列中每个元素均有过期时间,当从队列获取元素时,只有过期元素才会出队列。队列头元素是最块要过期的元素。
  • SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene;

饱和策略
当工作队列满且线程个数达到maximunPoolSize后所采取的策略

  • AbortPolicy:默认策略;新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
  • CallerRunsPolicy:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。
  • DiscardPolicy:丢弃新的任务,且不抛出异常。
  • DiscardOldestPolicy:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务
    自定义策略:根据用户需要定制。

参考:
https://zhuanlan.zhihu.com/p/87733949
https://blog.csdn.net/qq_33323054/article/details/106923732

相关文章

  • 9.线程池-2

    一、常见线程池介绍 上一节中线程池使用到了Executors.newSingleThreadExecutor()方...

  • 线程池

    线程池组件 1、线程池管理器(ThreadPoolManager):用于创建并管理线程池 2、工作线程(WorkT...

  • 线程池核心参数

    线程池核心参数 1)corePoolSize(线程池基本大小) 2)maximumPoolSize(线程池最大数量...

  • 线程池学习笔记

    1、线程池的定义 2、Executors创建线程池的方式 3、ThreadPoolExecutor对象 4、线程池...

  • 线程池(3)终止线程池原理

    终止线程池 一、终止线程池方法 1、 shutdown() 安全的终止线程池 2、 shutdownNow() 强...

  • 线程池相关知识

    线程池 1. 什么是线程池 线程的池化,一个线程的容器、集合,包含多个线程 2. 为什么要用线程池 线程对于操作系...

  • 线程池

    1、为什么要使用线程池2、线程池的工作原理3、线程池参数4、阻塞队列5、饱和策略6、向线程池提交任务7、线程池的状...

  • ScheduledThreadPoolExecutor线程池

    1. ScheduledThreadPoolExecutor线程池2. SpringBoot2.X整合定时线程池(...

  • 2019-03-13 自定义连接池

    连接池:即线程池要自定义先要了解线程池模型,即线程池的核心参数1.coresize核心线程池,即运行的线程2.ma...

  • 线程池

    目录: 1.线程池的作用2.线程池的种类3.线程池的使用 线程池的作用: 线程主要是通过控制执行的线程的数量,超出...

网友评论

      本文标题:9.线程池-2

      本文链接:https://www.haomeiwen.com/subject/naxyvltx.html