线程池的好处

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌

线程池的主要工作流程

从上图我们可以看出,当提交一个新任务到线程池时,线程池的处理流程如下:

首先线程池判断基本线程池是否已满?没满,创建一个工作线程来执行任务。满了,则进入下个流程。

其次线程池判断工作队列是否已满?没满,则将新提交的任务存储在工作队列里。满了,则进入下个流程。

最后线程池判断整个线程池是否已满?没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。

线程池的创建

我们可以通过ThreadPoolExecutor来创建一个线程池。

new ThreadPoolExecutor(corePoolSize, maximumPoolSize,

keepAliveTime, milliseconds,runnableTaskQueue, threadFactory,handler);

创建一个线程池需要输入几个参数:

  1. corePoolSize - 线程池核心池的大小。
  2. maximumPoolSize - 线程池的最大线程数。
  3. keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
  4. unit - keepAliveTime 的时间单位。
  5. workQueue - 用来储存等待执行任务的队列。
  6. threadFactory - 线程工厂。
  7. handler - 拒绝策略。

corePoolSize(线程池的基本大小)

当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。

maximumPoolSize(线程池最大大小):

线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。

keepAliveTime(线程活动保持时间)

线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。

TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。

runnableTaskQueue(任务队列)

用于保存等待执行的任务的阻塞队列。可以选择以下几个阻塞队列。

ArrayBlockingQueue

是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。

LinkedBlockingQueue

一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。

SynchronousQueue

一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。

PriorityBlockingQueue

一个支持优先级排序的无界阻塞队列。

DelayQueue

一个使用优先级队列实现的无界阻塞队列。

ThreadFactory

用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字,Debug和定位问题时非常有帮助。

RejectedExecutionHandler(饱和策略)

当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略。

  1. ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
  2. ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

当然也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。

线程池不允许使用Executors去创建

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors各个方法的弊端:

1)newFixedThreadPool和newSingleThreadExecutor

主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。

newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。

此线程池保证所有任务的执行顺序,按照任务的提交顺序(FIFO, LIFO, 优先级)执行。

newFixedThreadPool

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。

线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

可控制线程最大并发数,超出的线程会在队列中等待

2)newCachedThreadPool和newScheduledThreadPool

主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,

那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。

此线程池不会对线程池大小做限制

线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

newScheduledThreadPool

创建一个定时线程池,支持定时及周期性任务执行

线程池创建方式(推荐)

根据阿里巴巴java开发规范,推荐了3种线程池创建方式

推荐方式1:

首先引入:commons-lang3包

推荐方式 2:

首先引入:com.google.guava包

推荐方式 3:

spring配置线程池方式:自定义线程工厂bean需要实现ThreadFactory,可参考该接口的其它默认实现类,使用方式直接注入bean

调用execute(Runnable task)方法即可

linkedblockingqueue使用_阿里规范要求不能使用Executors创建线程相关推荐

  1. 阿里为何不允许用Executors创建线程池?

    点击下方"IT牧场",选择"设为星标" 作者:雪山上的蒲公英 cnblogs.com/zjfjava/p/11227456.html 1. 通过Executor ...

  2. 为什么阿里内部不允许用Executors创建线程池?

    来源:cnblogs.com/zjfjava/p/11227456.html 1. 通过Executors创建线程池的弊端 在创建线程池的时候,大部分人还是会选择使用Executors去创建. 下面是 ...

  3. 阿里内部禁用Executors创建线程池,为什么?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 何甜甜在吗 来源 | http://rrd.m ...

  4. 为什么阿里不允许用Executors创建线程池,而是通过ThreadPoolExecutor的方式?

    1.通过Executors创建线程池的弊端 在创建线程池的时候,大部分人还是会选择使用Executors去创建. 下面是创建定长线程池(FixedThreadPool)的一个例子,严格来说,当使用如下 ...

  5. 为什么阿里不允许用Executors创建线程池

    1 文章概述 <阿里巴巴JAVA开发手册>有这样一条强制规定:线程池不允许使用Executors去创建,而应该通过ThreadPoolExecutor方式,这样处理方式更加明确线程池运行规 ...

  6. 为什么阿里Java规约禁止使用Java内置Executors创建线程池?

    IDEA导入阿里规约插件,当你这样写代码时,插件就会自动监测出来,并给你红线提醒. 告诉你手动创建线程池,效果会更好. 在探秘原因之前我们要先了解一下线程池 ThreadPoolExecutor 都有 ...

  7. 阿里为什么禁用Executors创建线程池?

    作者 | 何甜甜在吗 来源 | http://rrd.me/eUh6V 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方 ...

  8. 阿里面试官鬼得很,问我为什么他们阿里要禁用Executors创建线程池?

    作者:何甜甜在吗 来源:http://rrd.me/eUh6V 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过 ...

  9. sql join on 多表连接_阿里规范不建议多表Join,可这SQL要怎么写啊?

    前言 我们先来看一下阿里开发手册的描述: 手册上写着[强制],但是我相信很多同学项目里面的代码都不满足这个要求.但是关键问题是:不用join,这SQL究竟要怎么写啊! 高性能MySQL 高性能MySQ ...

最新文章

  1. 无人驾驶:车道线检测,附代码
  2. do……while 循环
  3. 一看就懂,图解 Spring 循环依赖,写得老好了!
  4. P2014 选课 (树形动规)
  5. python动态改变标签的颜色_PyQt4 treewidget 选择改变颜色,并设置可编辑的方法
  6. Deep Learning---caffe模型参数量(weights)计算
  7. python3.6程序实例_Python3.6学习笔记(三)
  8. java获取0点的时间戳_Java获取凌晨时间戳的方法分析
  9. Oracle中的单行函数
  10. 信贷ABS资产静态池与动态池里的数据分析内容都有啥
  11. 如何打开.hdx文件
  12. vue.js手册_Vue手册:Vue.js的完整介绍
  13. Error response from daemon: removal of container XXX is already in progress
  14. Oracle存储过程取当天为当年的第几周(自然周),以及当年总周数
  15. 轻松打造开源安全信息管理平台
  16. Radius配置实例
  17. 软件测试就是挑Bug?也许你有认知偏差
  18. 八款windows设计软件,经典永流传
  19. matlab人眼识别原理,基于MATLAB的人眼检测.docx
  20. 游戏开发人员眼中的Unity 3D网页游戏測评报告

热门文章

  1. 二十万字C/C++、嵌入式软开面试题全集宝典十一
  2. 【特征】机器学习之特征优选
  3. [云炬创业基础笔记]第九章企业的法律形态测试8
  4. 2020教资高频考点作文素材汇总
  5. [云炬创业基础笔记]第二章创业者测试19
  6. [云炬创业基础笔记]第二章创业者测试16
  7. 科大星云诗社动态20210323
  8. 云炬60s看世界20211125
  9. 雨中赶班车 2019-12-19
  10. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170401