线程池的核心参数

一、线程池参数

  • corePoolSize 核心线程数目

  • maximumPoolSize 最大线程数目 = (核心线程+救急线程的最大数目)

  • keepAliveTime 生存时间 - 救急线程的生存时间,生存时间内没有新任务,此线程资源会释放

  • unit 时间单位 - 救急线程的生存时间单位,如秒、毫秒等

  • workQueue - 当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务

  • threadFactory 线程工厂 - 可以定制线程对象的创建,例如设置线程名字、是否是守护线程等

  • handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略

一个任务提交到线程池的流程

image.png 1,任务在提交的时候,首先判断核心线程数是否已满,如果没有满则直接添加到工作线程执行

2,如果核心线程数满了,则判断阻塞队列是否已满,如果没有满,当前任务存入阻塞队列

3,如果阻塞队列也满了,则判断线程数是否小于最大线程数,如果满足条件,则使用临时线程执行任务

如果核心或临时线程执行完成任务后会检查阻塞队列中是否有需要执行的线程,如果有,则使用非核心线程执行任务

4,如果所有线程都在忙着(核心线程+临时线程),则走拒绝策略

拒绝策略:

1.AbortPolicy:直接抛出异常,默认策略;

2.CallerRunsPolicy:用调用者所在的线程来执行任务;

3.DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;

4.DiscardPolicy:直接丢弃任务;

二、线程池创建方法

  1. 通过ThreadPoolExecutor构造方法创建

    • 这是最基础也是最灵活的创建线程池的方式。可以根据前面介绍的各种参数来自定义线程池
  2. 通过Executors工厂方法创建

  • Java 提供了 Executors 工厂类,它有一些方便的静态方法来创建常见的线程池。

  • 常见的工厂方法如下:

    • newFixedThreadPool(int nThreads) :创建一个固定大小的线程池,其核心线程数和最大线程数都等于参数 nThreads,任务队列是一个无界的 LinkedBlockingQueue。例如,Executors.newFixedThreadPool(5) 表示创建一个大小为 5 的固定线程池。

    • newCachedThreadPool() :创建一个可缓存的线程池。它的核心线程数为 0,最大线程数为 Integer.MAX_VALUE,当线程空闲时间超过 60 秒(默认值)时,线程会被回收。任务队列是一个 SynchronousQueue。这种线程池适合执行大量的短时任务,因为线程可以快速创建和回收。例如,在一个高并发的短时任务处理场景中,如处理 HTTP 请求的小型任务,可以使用这个线程池。

    • newSingleThreadExecutor() :创建一个单线程的线程池。它的核心线程数和最大线程数都为 1,任务队列是一个无界的 LinkedBlockingQueue。这种线程池适合用于需要保证任务按顺序执行的场景,比如日志记录任务,因为只有一个线程,可以保证任务的执行顺序和提交顺序一致。

    • newScheduledThreadPool(int corePoolSize) :创建一个支持定时和周期性任务的线程池。它和 newFixedThreadPool 类似,但是它是为定时任务设计的。可以用于任务调度,如定时发送邮件、定时备份数据等场景。