请详细解释Java中的线程池(ThreadPoolExecutor)的工作原理,并说明如何自定义线程池的拒绝策略

线程池(ThreadPoolExecutor)的工作原理

线程池是一种用于管理和复用线程的机制,可以有效地控制并发线程的数量,减少线程创建和销毁的开销。ThreadPoolExecutor是Java中实现线程池的核心类。

核心组件

  1. 核心线程数(corePoolSize):线程池中保持的最小线程数,即使这些线程处于空闲状态也不会被销毁。
  2. 最大线程数(maximumPoolSize):线程池中允许的最大线程数。
  3. 存活时间(keepAliveTime):当线程数超过核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。
  4. 工作队列(workQueue):用于保存等待执行任务的队列。
  5. 拒绝策略(RejectedExecutionHandler):当任务无法被接受时的处理策略。

工作流程

  1. 当一个任务提交到线程池时,如果当前线程数小于核心线程数,线程池会创建一个新的线程来执行任务。
  2. 如果当前线程数已经达到核心线程数,任务会被放入工作队列中等待执行。
  3. 如果工作队列已满,但当前线程数小于最大线程数,线程池会创建一个新的线程来执行任务。
  4. 如果当前线程数已经达到最大线程数,并且工作队列已满,新提交的任务将根据拒绝策略进行处理。

自定义线程池的拒绝策略

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

  1. AbortPolicy :默认策略,抛出RejectedExecutionException异常。
  2. CallerRunsPolicy:由调用线程执行任务。
  3. DiscardPolicy:直接丢弃任务,不抛出异常。
  4. DiscardOldestPolicy:丢弃工作队列中最老的任务,然后重新尝试执行新任务。

可以通过实现RejectedExecutionHandler接口来自定义拒绝策略。以下是一个自定义拒绝策略的示例:

java 复制代码
import java.util.concurrent.RejectedExecutionHandler; 
import java.util.concurrent.ThreadPoolExecutor; 

public class CustomRejectionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println("Task  " + r.toString()  + " rejected from " + executor.toString()); 
        // 可以在这里添加自定义的处理逻辑,例如记录日志、发送通知等
    }
}

使用自定义拒绝策略的示例:

ini 复制代码
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class ThreadPoolExample {
    public static void main(String[] args) {
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        CustomRejectionHandler rejectionHandler = new CustomRejectionHandler();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            corePoolSize,
            maximumPoolSize,
            keepAliveTime,
            unit,
            workQueue,
            rejectionHandler
        );

        for (int i = 0; i < 6; i++) {
            final int taskNumber = i;
            executor.submit(()  -> {
                System.out.println("Task  " + taskNumber + " is running.");
                try {
                    Thread.sleep(2000); 
                } catch (InterruptedException e) {
                    e.printStackTrace(); 
                }
                System.out.println("Task  " + taskNumber + " is completed.");
            });
        }

        executor.shutdown(); 
    }
}

在这个示例中,我们创建了一个自定义的拒绝策略CustomRejectionHandler,并在创建ThreadPoolExecutor时将其设置为拒绝策略。当任务无法被接受时,自定义拒绝策略会打印一条消息。

总结

线程池通过管理和复用线程,提高了系统的性能和稳定性。ThreadPoolExecutor提供了灵活的配置选项和自定义拒绝策略,可以根据具体需求进行调整。

相关推荐
保持学习ing24 分钟前
SpringBoot前后台交互 -- 登录功能实现(拦截器+异常捕获器)
java·spring boot·后端·ssm·交互·拦截器·异常捕获器
gadiaola30 分钟前
【JVM面试篇】高频八股汇总——类加载和类加载器
java·jvm·面试
七七&55635 分钟前
【Java开发日记】基于 Spring Cloud 的微服务架构分析
java·spring cloud·架构
小猫咪怎么会有坏心思呢44 分钟前
华为OD机考-数字游戏-逻辑分析(JAVA 2025B卷)
java·游戏·华为od
Aesopcmc1 小时前
idea 启动jar程序并调试
java·intellij-idea·jar
南极Ou1 小时前
Mybatis逆向工程详解(附源码文件)动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
xml·java·mybatis
Moshow郑锴1 小时前
IDEA为何一直无法使用超过4g内存
java·ide·intellij-idea
木头左1 小时前
Docker容器化镜像分层原理及优化策略
java·eureka
李少兄1 小时前
IntelliJ IDEA代码提示忽略大小写设置详解
java·ide·intellij-idea
白宇横流学长2 小时前
基于SpringBoot实现的课程答疑系统设计与实现【源码+文档】
java·spring boot·后端