Java线程池任务提交时队列满的处理策略

Java Q&A Hub 使用 GPT-4o-mini 回答

问题:

Java面试题之多线程 如果你提交任务时,线程池队列已满。会时发会生什么?

回答:

在Java中,如果你使用线程池(例如 ThreadPoolExecutor)提交任务时,线程池的队列已满,会发生以下情况,具体取决于你在创建线程池时所选择的拒绝策略(Rejection Policy)。

ThreadPoolExecutor 提供了四种默认的拒绝策略:

  1. AbortPolicy(默认策略):

    • 当线程池的队列已满且无法接受新的任务时,抛出 RejectedExecutionException。这意味着提交的任务会被拒绝,调用者需要处理这个异常。
  2. CallerRunsPolicy

    • 当线程池的队列已满时,调用者线程会被要求自己执行这个任务。这样可以减缓任务提交的速度,直到线程池有能力处理更多的任务。
  3. DiscardPolicy

    • 当线程池的队列已满时,直接丢弃提交的任务,不抛出异常。这意味着你可能会丢失一些重要的任务。
  4. DiscardOldestPolicy

    • 当线程池的队列已满时,丢弃队列中最旧的任务,然后尝试提交当前任务。这种策略可以确保新的任务能够被处理,但可能会导致旧任务的丢失。

在创建 ThreadPoolExecutor 时,你可以通过构造函数指定拒绝策略。例如:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(queueCapacity),
    new ThreadPoolExecutor.AbortPolicy() // 这里可以选择不同的拒绝策略
);

选择合适的拒绝策略取决于你的应用场景和对任务丢失的容忍度。