Java 线程池之 ThreadPoolExecutor

ThreadPoolExecutor 是 Java 提供的一个强大的线程池实现类,它允许我们灵活地配置和管理线程池的各种参数。ThreadPoolExecutor 可以通过设置核心线程数、最大线程数、线程存活时间、任务队列和拒绝策略等,满足不同场景下的并发需求。

1. ThreadPoolExecutor 构造函数

ThreadPoolExecutor 的构造函数如下:

public ThreadPoolExecutor(
    int corePoolSize,          // 核心线程数
    int maximumPoolSize,       // 最大线程数
    long keepAliveTime,        // 非核心线程的存活时间
    TimeUnit unit,             // 存活时间的单位
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,        // 线程工厂
    RejectedExecutionHandler handler    // 拒绝策略
)

2. 关键参数

  • corePoolSize:核心线程数,始终保持在线的线程数量,即使这些线程处于空闲状态。
  • maximumPoolSize:最大线程数,当任务队列已满且正在运行的线程数量小于最大线程数时,会创建新的线程来执行任务。
  • keepAliveTime:当线程数超过核心线程数时,多余的空闲线程存活的最长时间。超过这个时间后,多余的线程会被终止。
  • unitkeepAliveTime 的时间单位。
  • workQueue:用于存放等待执行任务的队列。
  • threadFactory:用于创建新线程的工厂类,可以用来为每个创建的线程设置名称和优先级等属性。
  • handler:拒绝策略,当任务无法提交到线程池时(任务队列已满且线程数达到最大值),会执行该策略。

3. 示例代码

下面是一个使用 ThreadPoolExecutor 的示例:

import java.util.concurrent.*;

public class ThreadPoolExecutorDemo {
    public static void main(String[] args) {
        // 创建任务队列
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10);

        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,        // 核心线程数
                4,        // 最大线程数
                60,       // 线程存活时间
                TimeUnit.SECONDS, // 时间单位
                workQueue,        // 任务队列
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
        );

        // 提交任务
        for (int i = 0; i < 20; i++) {
            executor.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " is executing task.");
                try {
                    Thread.sleep(2000); // 模拟任务执行时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

4. 拒绝策略

ThreadPoolExecutor 提供了几种内置的拒绝策略,可以在任务无法执行时采用:

  • AbortPolicy:默认策略,直接抛出 RejectedExecutionException
  • CallerRunsPolicy:调用执行自己的 execute 方法运行任务,即由调用者所在的线程来运行这个任务。
  • DiscardPolicy:直接丢弃任务,不抛出异常。
  • DiscardOldestPolicy:丢弃最老的一个任务,然后尝试重新提交当前任务。

可以通过实现 RejectedExecutionHandler 接口来自定义拒绝策略:

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 自定义处理逻辑
        System.out.println("Task rejected: " + r.toString());
    }
}

5. 自定义线程工厂

通过实现 ThreadFactory 接口,可以自定义线程的创建过程:

public class CustomThreadFactory implements ThreadFactory {
    private int threadId;
    private String name;

    public CustomThreadFactory(String name) {
        threadId = 1;
        this.name = name;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, name + "-Thread-" + threadId);
        System.out.println("Created new thread with id: " + threadId + " and name: " + t.getName());
        threadId++;
        return t;
    }
}

// 使用自定义线程工厂
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2,
    4,
    60,
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(10),
    new CustomThreadFactory("CustomThreadFactory"),
    new ThreadPoolExecutor.AbortPolicy()
);

6. 生命周期管理

ThreadPoolExecutor 提供了以下方法来管理线程池的生命周期:

  • shutdown():平滑关闭线程池,已提交的任务会继续执行,但不会接受新任务。
  • shutdownNow():立即关闭线程池,试图中断正在执行的任务,并返回未执行的任务列表。
  • isShutdown():判断线程池是否已关闭。
  • isTerminated():判断所有任务是否已完成。
  • awaitTermination(long timeout, TimeUnit unit):等待线程池在指定时间内关闭。
executor.shutdown();
try {
    if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
        executor.shutdownNow();
    }
} catch (InterruptedException e) {
    executor.shutdownNow();
    Thread.currentThread().interrupt();
}

总结

ThreadPoolExecutor 提供了丰富的配置选项,可以根据具体需求灵活地配置线程池的行为和策略。通过合理地使用线程池,可以显著提高应用程序的并发性能和资源利用率。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值