跟面试官谈【线程池】
目录
- What?
- Why?
- 分类?
- 1. newCachedThreadPool
- 1.1.what?
- 1.2 代码实例
- 1.3 执行结果
- 1.4 源码分析
- 1.5 缺点
- 2.newFixedThreadPool
- 2.1 What?
- 2.2 代码实例
- 2.3 结果
- 2.4 源码分析
- 2.5 缺点
- 3. newScheduledThreadPool
- 3.1 what
- 3.2 代码示例
- 3.3 执行结果
- 3.4 源码分析
- 3.5 缺点
- 4、newSingleThreadExecutor
- 4.1 what?
- 4.2 代码示例
- 4.3 运行结果
- 4.4 源码分析
- 4.5 缺点
- 线程池
- 1.线程池原理
- 2. 自定义线程池
- 3、 拒绝策略
- 4. 合理配置线程池
- 5.应用
- 总结
近期听到了很多求职小伙伴的心声,线程池不是很了解,而且只知道如果运用,更别提深层研究了,导致每次都被面试官问的哑口无言。那我就做回天使吧,给大家系统一下。
我的套路是从原理----应用----源码;让你彻底弄成线程池。
What?
线程池,就是一个池子嘛,但是这个池子不是装水的,而是装线程的;
想想我们平常水池的是啥,还不是为了用水的时候方便,节省了来回运水的时间;而且我们可以让水可以循环利用,水资源多么宝贵呀,节约了水资源;同理,当面试官再问你,线程池好处的时候,是不是就可以结合“水池作用”,跟面试官装一把了;
Why?
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- **提高响应速度。**当任务到达时,任务可以不需要等到线程创建就能立即执行。
- **提高线程的可管理性。**线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
分类?
多线程是采用了Executor框架。具体的类图关系如下;ThreadPoolExecutor是线程池创建的核心类。然后线程池的具体创建方式如下几种:
1. newCachedThreadPool
1.1.what?
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
1.2 代码实例
public class CacheThread {public static void main(String[] args) {ExecutorService cachThread= Executors.newCachedThreadPool();for (int i = 0; i <10 ; i++) {final int temp=i;cachThread.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"当前线程的==="+temp);}});}}
1.3 执行结果
由上图,我们也得出了结果:虽然线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
1.4 源码分析
1.5 缺点
最大线程数为Integer.MAX_VALUE,可能会创建很多的线程,然后导致OOM异常;
2.newFixedThreadPool
2.1 What?
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
2.2 代码实例
public class FixThread {public static void main(String[] args) {// 有5个线程ExecutorService fixThread= Executors.newFixedThreadPool(5);for (int i = 0; i <10 ; i++) {final int temp=i;fixThread.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"当前线程=="+temp);}});}}
}
2.3 结果
我们可以得出结论:因为线程池的大小是5,所以它的好处是可以循环利用线程,合理的分配资源,去执行任务;
2.4 源码分析
通过源码,可以看出,它是核心线程数和最大线程数是相同的,采用的是LinkedBlockQueue<>队列;
2.5 缺点
LinkedBlockQueue<>没有设定范围,它的值为Inter.Max_Value,这样类似于无界队列,然后会存储很多的线程,造成OOM异常;
3. newScheduledThreadPool
3.1 what
创建一个定长线程池,支持定时及周期性任务执行
3.2 代码示例
public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(5);for (int i = 0; i < 10; i++) {final int temp=i;scheduledExecutorService.schedule(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"当前线程"+temp);}},4, TimeUnit.SECONDS);}}
}
3.3 执行结果
延迟4秒执行,运算出下面结果
3.4 源码分析
通过源码分析,它底层也是 调用的ThreadPoolExecutor。
3.5 缺点
同newCachedThreadPool一样,最大线程数为Integer.MAX_VALUE,可能会创建很多的线程,然后导致OOM异常;
4、newSingleThreadExecutor
4.1 what?
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
4.2 代码示例
public class SingleThread {public static void main(String[] args) {ExecutorService singleThread= Executors.newSingleThreadExecutor();for (int i = 0; i <10 ; i++) {final int temp=i;singleThread.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"当前线程"+temp);}});}}
}
4.3 运行结果
只有一个线程在执行;
4.4 源码分析
4.5 缺点
同newFixThreadPool一样,LinkedBlockQueue<>没有设定范围,它的值为Inter.Max_Value,这样类似于无界队列,然后会存储很多的线程,造成OOM异常;
线程池
由上面的几中线程的创建方式,我们可以看出,他们底层都调用了 “ThreadPoolExecutor”,上面的方法都有弊端,所以我们可以用ThreadPoolExecutor然后自定义线程池,根据我们项目中的需要;
1.线程池原理
- 判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
- 线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
- 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
2. 自定义线程池
【案例一】此时运行5个任务===最大线程数+队列数
public class ThreadPoolExcutor {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor(1,2,60L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),new ThreadPoolExecutor.AbortPolicy());//此时运行5个任务,没有超过 最大线程数+队列数for (int i = 1; i <=5 ; i++) {final int temp=i;taskThread t1=new taskThread("任务线程");threadPoolExecutor.execute(t1);}}
}
class taskThread implements Runnable{private String taskName;public taskThread(String taskName){this.taskName=taskName;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"当前现成的任务"+taskName);}
}
运行的结果:
【案例二】:此时用了两个线程,进行了复用,但是我们如果尝试一下运行6个任务(超过了最大线程数+队列的数据);
运行结果:
由结果可知,我们也就更进一步的明白了线程池的运行原理,当我们执行的任务超过了 最大线程数+队列中的线程,然后线程池就会采用一些拒绝策略,进行拒绝;
3、 拒绝策略
- AbortPolicy(默认):直接抛出RejectedException异常,阻止系统正常运行;
- CallerRunsPolicy:不会抛弃任务也不会抛出异常,而是回退给调用者;
- DiscardOldestPolicy:丢弃等待最久的任务,然后把当前任务加入队列中;
- DiscardPolicy:直接丢弃任务,不做任何处理。
上面的例子中,我采用的是默认AbortPolicy的拒绝策略,然后直接抛异常,下面我演示一下用 “CallerRunsPolicy”进行调用,查看一下结果;
4. 合理配置线程池
我们在项目中使用线程池需要自定义最大线程数,那我们可以根据以下两点进行判断;
1 . IO密集型: 即该任务需要大量的IO,即大量的阻塞。在单线程上运行IO密集型的任务会导致浪费大量的;
这时候我们可以设定:最大线程数=CPU核数 * 2;
2 CPU密集型:该任务需要大量的运算,而没有阻塞,CPU一直全速运行。
这时候我们可以设定:最大线程数=CPU核数 ;
5.应用
在项目中我们需要多个任务的处理的时候,比如 使用多线程去消费mq中的数据等等;
总结
在跟面试官吹的时候,可以借鉴上面的思虑然后在加上在项目中的经验,调理清晰;让面试官也大开眼界,不选你,选谁!
跟面试官谈【线程池】相关推荐
- 面试官系统精讲Java源码及大厂真题 - 40 打动面试官:线程池流程编排中的运用实战
40 打动面试官:线程池流程编排中的运用实战 没有智慧的头脑,就像没有蜡烛的灯笼. --托尔斯泰 引导语 在线程池的面试中,面试官除了喜欢问 ThreadPoolExecutor 的底层源码外,还喜欢 ...
- 面试官一个线程池问题把我问懵逼了。
你好呀,我是why哥. 前几天,有个朋友在微信上找我.他问:why哥,在吗? 我说:发生肾么事了? 他啪的一下就提了一个问题啊,很快. 我大意了,随意瞅了一眼,这题不是很简单吗? 结果没想到里面还隐藏 ...
- main线程 子线程 顺序_面试官:线程池如何按照core、max、queue的执行顺序去执行?详解...
前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...
- adguard没有核心 core no_面试官:线程池如何按照core、max、queue的执行顺序去执行?...
前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...
- 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了)
title: 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) tags: 面试常见题 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) 腾讯面试题:创建索 ...
- 浅谈线程池(下):相关试验及注意事项
三个月,整整三个月了,我忽然发现我还有三个月前的一个小系列的文章没有结束,我还欠一个试验!线程池是.NET中的重要组件,几乎所有的异步功能依赖于线程池.之前我们讨论了线程池的作用.独立线程池的存在意义 ...
- 浅谈线程池(中):独立线程池的作用及IO线程池
在上一篇文章中,我们简单讨论了线程池的作用,以及CLR线程池的一些特性.不过关于线程池的基本概念还没有结束,这次我们再来补充一些必要的信息,有助于我们在程序中选择合适的使用方式. 独立线程池 上次我们 ...
- 浅谈线程池(上):线程池的作用及CLR线程池
线程池是一个重要的概念.不过我发现,关于这个话题的讨论似乎还缺少了点什么.作为资料的补充,以及今后文章所需要的引用,我在这里再完整而又简单地谈一下有关线程池,还有.NET中各种线程池的基础.更详细的内 ...
- Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流
Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流 前面讲了 Hystrix 的 request cache 请求缓存.fallback 优雅降级.circuit breaker 断路 ...
- Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离
Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离 上一讲提到,如果从 Nginx 开始,缓存都失效了,Nginx 会直接通过缓存服务调用商品服务获取最新商品数据(我们基于电商项目做 ...
最新文章
- Eclipse开发环境设置
- 美术干货:用Blender绘制low poly风格的游戏角色
- c++中声明和定义的区别(这个兄弟写的解决了我的疑惑)
- 原生js打印指定节点元素
- 西餐美食店响应式网站模板
- 互联网医生-ICMP协议
- 【南邮操作系统实验】页面置换算法 (FIFO、LRU、OPT)Java 版
- linux下limits.conf 修改不生效的原因
- kindle3 破解字体
- linux识别罗兰声卡,罗兰系列声卡直播K歌模式调试方法
- 51单片机下的温控智能小风扇
- R语言ggplot2可视化哑铃图、强调从一个点到另一个点的变化、数量的变化、客户满意度的变化等(Dumbbell Plot)、为可视化图像添加标题、题注信息
- Bytom BIP-32协议和BIP-44协议
- 2008年IT产业38个判断(转载)
- @ComponentScan注解
- 实验题目:约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,m为任意一个正整数。从第一个人开始顺时针方向自1起顺序报数,报到m时停止并且报m的人出列,再从他的下一个人
- 增量式旋转编码器的使用,以arduino为例
- 将字符串,数组等任意格式转为json(JSON)数据,Arrays是数组工具类,将任意数组转字符串或数组操作
- navigationController中navigationBar 的设置
- AAA服务器原理,路由交换学习笔记(十七)AAA基本原理