线程池_ThreadPoolExecutor参数_拒绝策略介绍

为什么要使用线程池?

因为在Java开发中线程的创建开销很大,需要JVM和OS完成大量工作。在高并发应用中频繁创建和销毁线程的操作是很低效的行为。

线程池的主要工作是:

  1. 提升性能:线程池能独立负责线程的创建、分配和维护。当执行大量异步任务时,将创建线程、调度线程和销毁线程的工作交给线程池,能够让其尽可能使用空闲的线程去执行异步任务,尽可能实现线程的复用,使得效率明显提升。
  2. 线程管理:线程池都会存储一些基本的线程统计信息,这些信息可以帮助我们对线程进行有效的监控和管理。

Java开发中创建线程的方法

通过Executors创建线程池

这是Java内置的几种线程池的创建方法。

不推荐在开发中使用,由于Executors的线程池创建使用的默认参数往往不符合开发的需求,尤其是默认使用无界队列(如LinkedBlockingQueue),会导致OOM问题(内存溢出)。

手动创建线程的方式

使用ThreadPoolExecutor,我们可以手动创建合适我们使用的线程池。

ThreadPoolExecutor构造函数的7个参数

  • corePoolSize:线程池中核心线程数
  • maximumPoolSize:线程池中能拥有最大线程数
  • keepAliveTime:表示空闲线程的存活时间
  • unit:表示keepAliveTime的单位
  • workQueue:用于缓存任务的阻塞队列
  • threadFactory:创建新线程时使用的工厂
  • handler:拒绝策略
public class ThreadPoolExample {
    public static void main(String[] args) {
        // 定义线程池参数
        int corePoolSize = 5; // 核心线程数
        int maximumPoolSize = 10; // 最大线程数
        long keepAliveTime = 60; // 线程空闲时间
        TimeUnit unit = TimeUnit.SECONDS; // 空闲时间单位
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10); // 任务队列
        ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略

        // 创建线程池
        ExecutorService executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler
        );

        // 提交任务到线程池
        for (int i = 1; i <= 10; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println("线程: " + Thread.currentThread().getName());
                // 这里可以放具体的任务逻辑
                // ...
            });
        }

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

四种拒绝策略的介绍

  • AbortPolicy

    默认的拒绝策略是中止策略。当线程池无法接受新的任务时,中止策略会让executor抛出一个RejectedExecutionException。

    适用场景:适用于对任务丢失敏感的场景,当线程池无法接受新任务时,希望立即知道并处理该异常。

  • CallerRunsPolicy

    CallerRunsPolicy会让调用者线程来执行任务,也就是采取同步调用的方式,间接控制了任务提交的流量。

    适用场景:适用于希望控制任务的提交流量,希望调用者自己处理被拒绝的任务的场景。

  • DiscardPolicy

    当无法提交新任务时,抛弃策略会抛弃该任务。

    适用场景:适用于对任务丢失不敏感的场景。

  • DiscardOldestPolicy

    DiscardOldestPolicy抛弃最旧策略首先从队列头部移除一个任务,然后重新提交新任务加入队列。

    适用场景:适用于对新任务优先级较高的场景,当线程池无法接受新任务时,会丢弃一些等待时间较长的旧任务,以便接受新任务。

如果要自定义拒绝策略,需要实现RejectedExecutionHandler接口。

class CustomRejectPolicy implements RejectedExecutionHandler {
    private final BlockingQueue<Runnable> workQueue;
    
    public CustomRejectPolicy(BlockingQueue<Runnable> workQueue) {
        this.workQueue = workQueue;
    }
    
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 将被拒绝的任务重新放入队列中等待执行
        try {
            workQueue.put(r);
        } catch (InterruptedException e) {
        //终断当前线程
            Thread.currentThread().interrupt();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值