# ThreadPoolExecutor

# 构造方法

ThreadPoolExecutor(int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler)
  • corePoolSize 核心线程数目 (最多保留的线程数)
  • maximumPoolSize 最大线程数目
  • keepAliveTime 生存时间 - 针对救急线程
  • unit 时间单位 - 针对救急线程
  • workQueue 阻塞队列
  • threadFactory 线程工厂 - 可以为线程创建时起个好名字
  • handler 拒绝策略

# 拒绝策略

JDK 提供了4中拒绝策略

  • AbortPolicy(默认策略) 让调用者抛出 RejectedExecutionException 异常
  • CallerRunsPolicy 让调用者运行任务
  • DiscardPolicy 放弃本次任务
  • DiscardOldestPolicy 放弃队列中最早的任务,本任务取而代之

# 工作模式

  • 线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。
  • 当线程数达到 corePoolSize 并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue 队列排队,直到有空闲的线程。
  • 如果队列选择了有界队列,那么任务超过了队列大小时,会创建 maximumPoolSize - corePoolSize 数目的线程来救急。
  • 如果线程到达 maximumPoolSize 仍然有新任务这时会执行拒绝策略。拒绝策略 jdk 提供了 4 种实现

根据这个构造方法,JDK Executors 类中提供了众多工厂方法来创建各种用途的线程池

# 关闭线程池

# shutdown

线程池状态变为 SHUTDOWN,不会接收新任务,但已提交任务会执行完,此方法不会阻塞调用线程的执行

# shutdownNow

线程池状态变为 STOP,不会接收新任务,会将队列中的任务返回,并用 interrupt 的方式中断正在执行的任务

# 其它方法

  1. isShutdown 不在 RUNNING 状态的线程池,此方法就返回 true

  2. isTerminated 线程池状态是否是 TERMINATED

  3. awaitTermination 调用 shutdown 后,由于调用线程并不会等待所有任务运行结束,因此如果它想在线程池 TERMINATED 后做些事情,可以利用此方法等待

# 异常处理

  1. try-catch
@Slf4j
public class ABA {
    public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.schedule(() -> log.info("start"), 1L, TimeUnit.SECONDS);

        pool.schedule(() -> {
            try {
                int i = 5 / 0;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }, 1, TimeUnit.SECONDS);

    }
}
  1. Future
@Slf4j
public class ABA {
    public static void main(String[] args) throws Exception {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.schedule(() -> log.info("start"), 1L, TimeUnit.SECONDS);

        //schedule,也可以submit
        ScheduledFuture<Boolean> future = pool.schedule(() -> {
            int i = 5 / 0;
            //这里的返回信息以实际业务为准
            //如果不返回,会被当作runnable
            return true;
        }, 1, TimeUnit.SECONDS);

        log.info("future:{}", future.get());

    }
}