请详细解释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提供了灵活的配置选项和自定义拒绝策略,可以根据具体需求进行调整。

相关推荐
shejizuopin2 分钟前
基于JavaSSM+MySQL的实验室考勤管理系统设计与实现
java·mysql·vue·毕业设计·论文·springboot·实验室考勤管理系统设计与实现
J***516813 分钟前
SpringSecurity的配置
java
面汤放盐15 分钟前
软件架构指南 Software Architecture Guide
java·微服务·devops
tkevinjd15 分钟前
JUC5(线程池)
java·线程池·多线程·juc
Tao____16 分钟前
如何对接Modbus-tcp协议(使用Thinlinks物联网平台)
java·物联网·网络协议·tcp/ip·modbus
鱼跃鹰飞20 分钟前
经典面试题:K8S的自动缩扩容和崩溃恢复
java·容器·kubernetes
Coder_Boy_24 分钟前
Spring Boot 事务回滚异常 UnexpectedRollbackException 详解(常见问题集合)
java·spring boot·后端
青云交26 分钟前
Java 大视界 -- 基于 Java+Redis Cluster 构建分布式缓存系统:实战与一致性保障(444)
java·redis·缓存·缓存穿透·分布式缓存·一致性保障·java+redis clus
不知疲倦的仄仄27 分钟前
第五天:深度解密 Netty ByteBuf:高性能 IO 的基石
java·开源·github
xiaobaishuoAI30 分钟前
后端工程化实战指南:从规范到自动化,打造高效协作体系
java·大数据·运维·人工智能·maven·devops·geo