博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程池的工作原理是啥?能手写一个线程池吗?
阅读量:4290 次
发布时间:2019-05-27

本文共 2192 字,大约阅读时间需要 7 分钟。

【原创】 Java识堂  

面试官:线程池的工作原理是啥?能手写一个线程池吗?

 

为什么要有线程池这个东西?

创建线程对象不像其他对象一样在JVM分配内存即可,还要调用操作系统内核的API,然后操作系统为线程分配一系列的资源,这个成本就很高了。所以线程是一个重量级对象,应该避免频繁创建和销毁

再说一下线程池的大概工作流程

以前我们运行线程的时候new Thread().start()即可,如果线程数多了,频繁的创建线程和销毁线程很费时间。

然后Doug Lea就这样设计了一下,预先启动几个线程,还准备好一个容器。每次想执行任务时,就将实现了Runnable接口的任务放到这个容器中,预先启动好的线程不断从容器中拿出任务,调用执行Runnable接口的run方法,这样刚开始启动的线程就能执行很多次任务。大概流程就是这样,真正的线程池考虑的东西比较多。

想到没有,这就是典型的生产者-消费者模式,线程池的使用者是生产者,线程池本身是消费者。用代码来实现一下

面试官:线程池的工作原理是啥?能手写一个线程池吗?

 

验证代码(正常工作)

面试官:线程池的工作原理是啥?能手写一个线程池吗?

 

来看一下Java中的线程池类ThreadPoolExecutor的构造函数有哪些参数?

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue
workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)

来类比学习一下这些参数,我们把线程池类比为项目组,线程是这个公司的成员

corePoolSize:线程池中最少的线程数,一个项目组总得有corePoolSize人坚守阵地,都是签订劳动合同了,不能随便撤。

maximumPoolSize:当项目很忙时,就得加人,请其他项目组的人来帮忙。但是公司空间有限,最多只能加到maximumPoolSize个人。当项目闲了,就得撤人了,最多能撤到corePoolSize个人

keepAliveTime & unit:上面提到项目根据忙闲来增减人员,那在编程世界里,如何定义忙和闲呢?如果一个线程在keepAliveTime(时间数字)* unit(时间单位)时间内都没有执行任务,说明这个线程很闲。如果此时线程数大于corePoolSize,这个线程就要被回收了

workQueue:就是任务队列

threadFactory:自定义如果创建线程,例如给线程指定一个有意义的名字

handler:workQueue满了(排期满了),再提交任务,该怎么处理呢?这个就是处理策略,线程池提供了4种策略,你也可以实现RejectedExecutionHandler接口来自定义策略

面试官:线程池的工作原理是啥?能手写一个线程池吗?

 

现在你可以去看看jdk提供的ThreadPoolExecutor类,发现原来也没那么难理解,为了方便大家练习,我把可以粘贴的代码放上来,方便大家粘贴

public class MyThreadPool { /** 利用阻塞队列实现生产者-消费者模式 */ BlockingQueue
workQueue; /** 保存内部工作线程 */ List
workThreadList = new ArrayList<>(); MyThreadPool(int poolSize, BlockingQueue
workQueue) { this.workQueue = workQueue; for (int i = 0; i < poolSize; i++) { WorkThread workThread = new WorkThread(); workThread.start(); workQueue.add(workThread); } } void execute(Runnable command) { // 放入任务,如果没有空间,则阻塞等待 // try catch部分省略 workQueue.put(command); } class WorkThread extends Thread { @Override public void run() { // 循环取任务并执行 while (true) { Runnable task = null; // 获取阻塞队列的第一个任务,并删除 // 如果没有元素,则会阻塞等待 // try catch部分省略 task = workQueue.take(); task.run(); } } } public static void main(String[] args) { BlockingQueue
workQueue = new LinkedBlockingQueue<>(5); MyThreadPool pool = new MyThreadPool(2, workQueue); for (int i = 0; i < 10; i++) { int num = i; pool.execute(()->{ System.out.println("线程 " + num + " 执行"); }); } }}

面试官:线程池的工作原理是啥?能手写一个线程池吗?

 

 

转载地址:http://ekggi.baihongyu.com/

你可能感兴趣的文章
为什么百度只抓取了首页而不抓取我的网站的内页的原因分析
查看>>
年薪170万的阿里P8级员工征婚有感--话说阿里真有钱,这员工要求的条件真多
查看>>
又是一年桂花飘香时,祝我们伟大的祖国70年华诞更加繁荣昌盛,祝大家国庆节快乐
查看>>
谷歌浏览器chrome即将在2020年底停止支持flash,我们程序员该怎么办
查看>>
如何将数据采集到 Elasticsearch 服务
查看>>
面试官:mysql表设计要注意什么?
查看>>
一些精致小众网站收集录
查看>>
计算机科学探秘之linux发展史
查看>>
程序员每天早上早来10分钟的好处
查看>>
互联网30年,泡沫如梦,一个个泡沫和风口过后,会是什么样的结局
查看>>
升级centos 6.8 服务器的gcc
查看>>
API网关在微服务架构中的应用,这一篇就够了
查看>>
JVM发生内存溢出的8种原因、及解决办法
查看>>
SpringBoot2.0 基础案例(12):基于转账案例,演示事务管理操作
查看>>
高性能负载均衡:nginx搭建tomcat集群
查看>>
Spring切面中的正则表达式
查看>>
一直再说高并发,多少QPS才算高并发?
查看>>
Git恢复之前版本的两种方法reset、revert(图文详解)
查看>>
Maven打包的三种方式
查看>>
电商场景:并发扣库存,怎么保证不超卖又不影响并发性能
查看>>