您的位置:

线程池策略详解

一、线程池策略选择

线程池在多线程编程中起到了至关重要的作用,可以有效地管理线程,提高系统的性能,降低线程创建和销毁带来的开销。在使用线程池时,我们需要注意选择适合当前系统的线程池策略。

Java提供的线程池主要有四种策略:

  • FixedThreadPool:一个固定大小的线程池,管理一组最多的线程,如果有多余的任务,则将其放入队列中等待运行。
  • CachedThreadPool:一个可变大小的线程池,根据需要创建新线程,当有线程空闲时会重复利用已创建的线程。
  • SingleThreadExecutor:只有一个线程的线程池,顺序执行每一个任务。
  • ScheduledThreadPool:类似于FixedThreadPool,但可以定时执行任务或延迟执行任务。

二、线程池什么时候触发拒绝策略

当线程池中线程的数量达到最大值并且任务队列已经满时,新提交的任务将会触发线程池拒绝策略。

三、线程池策略模式

线程池使用策略模式来定义不同的拒绝策略。Java提供了四种默认的拒绝策略:AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy和DiscardPolicy。

四、线程池拒绝策略参数

线程池中有两个参数与拒绝策略相关:corePoolSize和maximumPoolSize。corePoolSize 表示线程池中核心线程的数量,maximumPoolSize 表示线程池中最大线程的数量。如果线程池中线程数量未达到 corePoolSize,则会创建一个新的线程执行任务;如果达到 corePoolSize 并且任务队列已满,则会按照线程池策略拒绝任务。

五、线程池策略CallerRunsPolicy

CallerRunsPolicy 是 JDK 内置的拒绝策略之一,当线程池无法执行任务时,将任务直接交给调用 execute 方法的线程执行。

public class CallerRunsPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

六、线程池抛弃策略

DiscardPolicy 是 JDK 内置的拒绝策略之一,当线程池无法执行任务时,直接丢弃该任务。

public class DiscardPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // do nothing
    }
}

七、线程池callrun策略

CallerRunsPolicy 是 JDK 内置的拒绝策略之一,当线程池无法执行任务时,将任务直接交给调用 execute 方法的线程执行。

public class CallerRunsPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

八、线程池应该采取哪种拒绝策略

选择线程池拒绝策略需要根据实际场景,不同的拒绝策略有不同的应用场景。

  • AbortPolicy:默认的拒绝策略,在任务无法执行时直接抛出异常。
  • CallerRunsPolicy:当线程池中已有正在执行的线程时,调用 execute 方法的线程将直接执行待执行的任务。
  • DiscardPolicy:当任务无法执行时直接丢弃该任务。
  • DiscardOldestPolicy:当任务无法执行时丢弃一些队列中最老的任务,并将新任务加入队列。

九、线程池拒绝策略

用户也可以自定义拒绝策略,只需实现 RejectedExecutionHandler 接口并实现 rejectedExecution 方法即可。例如,我们可以将无法执行的任务写入日志等。

public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // my custom rejection policy
    }
}

十、线程池饱和策略选取

线程池的饱和策略选取需要根据实际情况进行选择。如果希望能够快速响应并抛出异常,则可以选择 AbortPolicy 等策略;如果希望利用已有线程执行任务,则可以选择 CallerRunsPolicy 等策略;如果希望最大限度地利用系统资源,则可以选择 DiscardOldestPolicy 或自定义拒绝策略。