写点什么

面试官:谈谈你对线程池的理解

  • 2021 年 11 月 12 日
  • 本文字数:1573 字

    阅读完需:约 5 分钟

那如果说,线程池中的线程已经到达最大线程数并且都在繁忙,还有新的任务进来,好比银行已经坐满人了,窗口也都在忙,客户都排到门口了,这时要是还有人要办理,应该怎么处理呢?银行一般会让这个人先回家,改天再来办,或者如果是个大客户,银行可能会单独带去 VIP 办公室办理等等。线程池在这种情况下也有相应的处理方式,这种处理方式我们称之为拒绝策略,如果会放任务在当前线程执行,或者直接将任务丢弃等等,在后面的章


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


节中我会详细给大家介绍。


JDK 中的线程池


========


在 JDK 中提供了相应的 API 来创建线程池,这些 API 也是在我们最近讲到过的 JUC 包中。



Executor


========


首先,线程池需要具备能够执行任务的能力,这个任务通过一个线程来处理。而这个执行任务的能力通过 Executor 接口来约定。


public interface Executor {


void execute(Runnable command);


}


ExecutorService


===============


在某些场景我们需要知道任务执行完之后的结果,拿到返回值,而 Runnable 接口是没有返回值的;以及一些可以关闭线程池中的线程,执行线程中的任务的方法,定义在 ExecutorService 接口中。



ThreadPoolExecutor


==================


ThreaPoolExecutor 是对 ExecutorService 的具体实现类,通过 ThreaPoolExecutor 类可以创建出一个线程池,我们先来看一下代码。


ThreadPoolExecutor executor = new ThreadPoolExecutor(


// 核心线程数 corePoolSize


3,


// 最大线程数 maximumPoolSize


5,


// 空闲线程保留存活的时间和时间单位


10, TimeUnit.SECONDS,


// 等待队列


new ArrayBlockingQueue<>(3),


// 创建线程的工厂


Executors.defaultThreadFactory(),


// 拒绝策略


new ThreadPoolExecutor.AbortPolicy()


);


从代码我们可以看出,创建一个线程池,需要指定我们上面说到的核心线程数,最大线程数,等待队列,拒绝策略等,并且还要指定创建线程的工厂对象。


当然 ThreadPoolExecutor 也有其他的构造方法,可以不显式指定拒绝策略和工厂对象。


new ThreadPoolExecutor(3,5,10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3));


// 构造方法


public ThreadPoolExecutor(int corePoolSize,


int maximumPoolSize,


long keepAliveTime,


TimeUnit unit,


BlockingQueue<Runnable> workQueue) {


// 使用默认的线程工厂和默认的拒绝策略。


this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,


Executors.defaultThreadFactory(), defaultHandler);


}


7 个线程池参数


=======


  • corePoolSize:核心线程数

  • maximumPoolSize:最大线程数

  • keepAliveTime:空闲线程保持存活时间

  • unit:空闲线程保持存活时间单位

  • workQueue:等待队列

  • threadFactory:线程工厂

  • RejectedExecutionHandler:拒绝策略


4 种拒绝策略


======


这里我们说一下 4 中拒绝策略。接口 RejectedExecutionHandler 定义了拒绝策略,所有的拒绝策略都需要实现该接口。


public interface RejectedExecutionHandler {


void rejectedExecution(Runnable r, ThreadPoolExecutor executor);


}


在 ThreadPoolExecutor 类中定义了 4 个拒绝策略的具体实现。


  • AbortPolicy:拒绝处理,抛出异常

  • CallerRunsPolicy:由创建该线程的线程(main)执行

  • DiscardPolicy:丢弃,不抛出异常

  • DiscardOldestPolicy:和最早创建的线程进行竞争,不抛出异常


可通过如下方式进行拒绝策略的创建。


// 拒绝处理,抛出异常


new ThreadPoolExecutor.AbortPolicy();


// 由创建该线程的线程(main)执行


new ThreadPoolExecutor.CallerRunsPolicy();


// 丢弃,不抛出异常


new ThreadPoolExecutor.DiscardPolicy();


// 和最早创建的线程进行竞争,不抛出异常


new ThreadPoolExecutor.DiscardOldestPolicy();


4 种线程池种类


=======


那么具体我们在使用时应该创建怎样的线程池呢?在 JDK 的 Executors 工具类为我们提供了 4 种线程池的创建方式。

评论

发布
暂无评论
面试官:谈谈你对线程池的理解