一、架构说明:

二、为什么使用线程池,优势是什么?

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,那么超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。

特点:线程复用、控制最大并发数量、管理线程

优点:

  • 降低资源消耗。通过重复利用已创建的线程来降低线程创建和销毁造成的消耗。
  • 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
  • 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅仅会消耗系统资源,还会降低体统的稳定性,使用线程可以进行统一分配,调优和监控。

2、特点:

newFixedThreadPool():执行长期任务,性能好很多

newSingleThreadExecutor():一个任务一个任务顺序执行

newCachedThreadPool():是一种用来处理大量短时间工作任务的线程池

代码演示:

public class MyThreadPoolDemo {
public static void main(String[] args) { // ExecutorService executorService = Executors.newFixedThreadPool(5); //一次有5个处理线程
// ExecutorService executorService = Executors.newSingleThreadExecutor();
// ExecutorService executorService = Executors.newCachedThreadPool(); //真实项目中使用
ExecutorService executorService = new ThreadPoolExecutor(2, 3, 1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
try {
//模拟10个用户来办理业务
for (int i = 0; i < 12; i++) { // try {
// TimeUnit.SECONDS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 办理业务");
});
} } catch (Exception e) {
e.printStackTrace();
}finally {
executorService.shutdown();
}
}
}  

三、ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}  

四、线程池七大参数介绍

corePoolSize:线程池的核心线程数

maximumPoolSize:线程池的最大线程数,此值必须大于等于1

keepAliveTime:多余的空闲线程的存活时间,线程池数量超过corePoolSize,空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到剩下corePoolSize个线程为止

TimeUnit:keepAliveTime的单位

workQueue:任务队列,被提交但是尚未被执行的任务

threadFactory:设置创建线程的工厂

p.p1 { margin: 0; font: 15px Helvetica }

RejectedExecutionHandler:拒绝策略,当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler 来处理

五、线程池底层工作原理

1、在创建了线程池后,等待提交过来的任务请求。

2、ThreadPoolExecutor执行execute方法,线程池会做如下判断:

  • 如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
  • 如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
  • 如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
  • 如果创建新线程将使当前运行的线程超出maximumPoolSize,线程池会启用拒绝策略来执行。

3、当一个线程完成任务,会从队列中取下一个任务来执行

4、当线程空闲时间达到keepAliveTime值时,线程池会判断,如果当前线程数大于corePoolSize,那么这个线程就会被停掉。

所以线程池的所有任务完成后最终会收缩到corePoolSize的大小。

六、线程池的4种拒绝策略

当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务

  • AbortPolicy(默认):直接抛出现RejectedExecutionException异常。
  • CallerRunsPolicy:该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量
  • DiscardOldestPolicy:丢弃队列里等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
  • DiscardPolicy:直接丢弃掉,不予任何处理也不抛出异常。

六、工作中线程池实际使用

public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(2, 3, 1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
}
}  

六、线程池配置合理线程数

查看电脑cpu核数:

public class CPUCoresDemo {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
}
}

1、CPU密集型:任务需要大量的运算,而没有阻塞,CPU一直全速运行。

CPU密集型任务配置尽可能的少的线程数量,

公式:CPU核数 + 1个线程的线程池。

2、IO密集型:任务需要大量的IO,即大量的阻塞

由于IO密集型任务线程并不是一直在执行任务,可以多分配一点线程数,如 CPU * 2 。

使用公式:CPU 核数/(1-阻塞系数);其中阻塞系数在 0.8 ~ 0.9 之间。

  

java面试-线程池使用过吗,谈谈对ThreadPoolExector的理解的更多相关文章

  1. Java面试——线程池

    1.类比介绍 假如有一个工厂,工厂里面有10个工人,每个工人同时只能做一件任务. 因此只要当10个工人中有工人是空闲的,来了任务就分配给空闲的工人做: 当10个工人都有任务在做时,如果还来了任务,就把 ...

  2. 深入理解Java之线程池(爱奇艺面试)

    爱奇艺的面试官问 (1) 线程池是如何关闭的 (2) 如何确定线程池的数量 一.线程池销毁,停止线程池 ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown() ...

  3. Java:线程池

    Java:线程池 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 获取多线程的方法: 实现 Runnable 接口 实现 Callable 接口 实例化 Thre ...

  4. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  5. Java中线程池的学习

    线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程 ...

  6. java利用线程池处理集合

    java利用线程池处理集合 2018年07月23日 17:21:19 衍夏成歌 阅读数:866   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/s ...

  7. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  8. [转]深入理解Java之线程池

    原文链接 原文出处: 海 子 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这 ...

  9. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

随机推荐

  1. 为什么说USDN是一种应用型稳定币?

    USDN是由NGK Global出品的一种新型稳定币系统,里面是涵盖了包括货币供需.Bancor.抵押借贷等在内的一整套算法.该稳定币构想一经提出,便在社区引发了不小的热度. 官方对于USDN的定位是 ...

  2. Captain Technology INC浅谈新能源汽车的未来

    近日全世界上最大的资管公司贝莱德向位于的英国电动汽车初创公司Arrival投资1.18亿美元,且该公司已有投资者亚马逊和美国第二大汽车制造商福特汽车参投.中国最知名的电动车公司蔚来股价单日大涨22%, ...

  3. windows server2012 搭建FTP服务器过程

    搭建过程链接地址:https://blog.csdn.net/smalllu161226/article/details/53887751 1.打开windows server2012R2 服务器管理 ...

  4. 缓存cache和缓冲区buffer

    一.cache 1.cache的定义.从宏观上讲,缓存是处理速度不匹配的问题.可以是静态缓存(内存缓存.磁盘缓存).动态缓存(前端的缓存)和数据库缓存.另一个角度,从CPU来看,可以是寄存器和内存之间 ...

  5. Oracle VM VirtualBox下创建CentOS虚拟系统

    下载镜像 创建虚拟电脑 点击新建,输入服务器命名(根据自己喜好),选择好类型和版本(我下载的是64位的CentOS系统,所以选择类型为Linux,版本为其他版本). 修改内存大小 系统建议为512M, ...

  6. 用于功率集成电路应用的600伏、10安、4H-SIC横向单沟道金属氧化物半导体场效应晶体管的演示和分析

    用于功率集成电路应用的600伏.10安.4H-碳化硅横向单沟道金属氧化物半导体场效应晶体管的演示和分析 摘要: 本文报道了一个具有大电流处理能力(10 A)的600伏4H-碳化硅横向场效应晶体管的演示 ...

  7. 剑指 Offer 32 - II. 从上到下打印二叉树 II + 层次遍历二叉树 + 按层存储

    剑指 Offer 32 - II. 从上到下打印二叉树 II Offer_32 题目描述: 题解分析: 这道题我一开始想到的解决方法较粗暴,就是使用两个变量来记录当前层的节点数和下一层的结点数. 以上 ...

  8. LeetCode-祖父节点值为偶数的结点值之和

    祖父节点值为偶数的结点值之和 LeetCode-1315 这题稍微难度有点大,但是仔细思考还是可以找到思路的. 因为只需要找到祖父节点这最上两层,所以可以带一个参数记录一下祖父节点是否是偶数,以及父节 ...

  9. LeetCode-二叉树的深度

    二叉树的深度 二叉树的深度 使用递归求解二叉树的深度. 需要注意使用的临界条件. /** * 任意一个二叉树的最大深度 **/ #include<iostream> #include< ...

  10. 基于4H-SIC的先进集成电路用n型LDMOS晶体管

    基于4H-SIC的先进集成电路用n型LDMOS晶体管 摘要: 通过对具有不同的设计方式的具有减小的表面电场的横向4H-SIC-N型-横向扩散金属氧化物半导体(LDMOS)晶体管进行测量和模拟,得到了得 ...