面试必问:来说说你是怎么使用线程池的?本文教你如何完美回答!

本文详细探讨了线程池的使用目的、创建过程和常见面试问题,包括线程池的四种版本演化,Java线程池的阻塞队列类型,不推荐使用的默认线程池,拒绝策略,以及核心线程数和最大线程数的配置建议。通过实例分析,帮助读者深入理解线程池的关键参数和应用场景。
摘要由CSDN通过智能技术生成

前言

Java中的线程池用过吧?来说说你是怎么使用线程池的?
在这里插入图片描述

这句话在我面试过程中遇到过好几次了,虽然线程池是一个已经被说烂的知识点了,但是还是要写这一篇用来加深自己的印象,但是今天想使用一个特殊的方式写出来。
码字不易,希望能够获得你的赞与评论~

线程池

使用线程池的目的

先说一下我们为什么要使用线程池?

  • 线程是稀缺资源,不能频繁的创建。而且创建和销毁线程也是比较占用系统开销的。
  • 为了做到解耦,线程的创建与执行任务分开,方便对线程进行维护。
  • 为了复用,前面也说了创建和销毁线程比较耗系统开销,那么创建出来线程放到一个池子里,可以给其他任务进行复用。

线程池是如何一步一步创建的

第一版

正常的我们在创建一个线程去执行任务的时候是这样的:

new Thread(r).start();

但是这是最基本的方式,我们的项目中有可能很多地方都需要创建一个新的线程。这个使用为了减少重复代码,我们会把这段创建线程的代码放的一个工具类里面,然后对外提供工具方法,使用的时候直接调用此方法即可。

第二版

/**
 * 先定义接口(任务执行器)
 */
public interface Executor {
   
    /**
     * 执行任务
     * @param runnable  线程任务
     */
    void execute(Runnable runnable);
}
/**
 * 实现:直接创建线程。
 */
class ExecutorImpl implements Executor {
   
    public void execute(Runnable r) {
   
        new Thread(r).start();
    }
}

这种方式实现了创建线程的代码的复用,但是并没有实现线程资源的复用,当有1000个地方需要线程的时候,会创建1000个线程。

第三版

为了实现资源也复用,增加一个阻塞队列,当来了创建线程的任务的时候,先放到队列里,然后再用一个线程(Worker),来处理任务。这样就完成了线程资源的复用了,全程只有一个线程在来回的复用,一直在处理队列中的任务。
在这里插入图片描述

通过上面的方式,实现了线程资源的复用,并且也起到提交任务和处理任务之间的解耦。但是只有一个线程处理任务,会有瓶颈的,所以具体需要多少线程来处理任务最好是根据具体的业务场景来确定,这样我们把这个值,设置成一个参数,当创建线程池的时候传入,就叫corePoolSize吧。

而且任务队列最好也要有容量,但也应该是根据业务场景来配置容量,而且任务队列还可以定制一些规则,例如:按照一定的规则出队。所以我们把任务队列也配置成参数,在创建线程池的时候传入。参数名称就叫:workQueue吧。

当队列中任务满了之后,任务就会被抛弃,但是如果是重要业务任务,还不能抛弃,所以,当队列中任务满了之后,在线程池没有资源处理任务的时候,拒绝策略,我们也根据业务场景来确定,这样也在创建的时候传入一种拒绝策略,参数名称就叫:rejectedExecutionHandler

继续优化

虽然多了上面的三个参数后效果优化了不少,但是还可以继续优化:

并不用上来就创建corePoolSize数量的线程,我们可以增加了一个变量workCount,来记录已经创建出来了工作线程,这样在初始化的时候只有workCount<corePoolSize的时候,我们才创建线程来执行任务,当workCount>CorePoolSize的时候,再来了任务,就去进队列。
在增加拒绝策略的时候,我定义一个接口:RejectedExecutionHandler,然后使用者可以自己去实现这个接口,来完成自己的拒绝策略。
增加一个线程工厂的入参:ThreadFactory,这样保证每次创建线程的时候不用手动去创建线程了,而是通过ThreadFactory来获取线程,并且也可以增加一些线程的标识。

第四版

虽然说第三版的线程池已经可以应对日常工作中的情况了,但是还是不够有弹性,所谓的弹性就是指,在任务提交频繁时应该处理能力提高,任务提交不频繁时处理能力应该降低。

上面这版线程池就不够弹性。

如果某个时间段,任务提交量剧增,这个时候,corePoolSize和队列都满了,再来提交任务就只能走拒绝策略了。

你或许会想到,那我可以增大corePoolSize的值,这样就会创建出来更多的线程来处理任务,但是这个任务提交量剧增,只是某个时间段,过了这个时间段之后,创建出来这么多的线程,可以大部分都会是空闲的状态。这样也是浪费资源了。

这样就导致了一个两难的情况,corePoolSize的值设置太大了也不好,设置太小了也不好。

这个时候,为让线程池做到弹性伸缩,我们可以为他再添加一个参数:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值