线程池 ThreadPoolExecutor 简单使用

本文围绕 Java 的 ThreadPoolExecutor 展开,介绍了创建线程池、线程工厂、自定义拒绝策略及测试。以提交 100 个任务为例,阐述任务执行流程,还根据线程池配置计算运行时长,实际多线程运行时长为 7169 ms。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ThreadPoolExecutor 是 java.util.concurrent 包下的类

一、创建线程池
public class ThreadPoolConfig {

    private static volatile ThreadPoolExecutor threadPoolExecutor = null;

    private ThreadPoolConfig() {
    }

    /* int corePoolSize: 核心线程数
     * int maximumPoolSize: 最大线程数,及当前线程允许创建多少个线程
     * long keepAliveTime && TimeUnit unit: 表示线程池没任务,线程存活多久销毁
     * BlockingQueue<Runnable> workQueue: 任务队列大小,如果不设置默认大小为Integer.MAX_VALUE
     * ThreadFactory threadFactory: 线程工厂,创建线程时用,一般用来给线程设置参数,比如线程名
     * RejectedExecutionHandler handler: 拒绝策略,如果线程池满了,新来的线程怎么处理,默认策略 java.util.concurrent.AbortPolicy
     */

    public static synchronized ThreadPoolExecutor getInstance() {
        if (null == threadPoolExecutor) {
            threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(60), new MyThreadFactory(), new MyRejectedExecutionHandler());
        }
        return threadPoolExecutor;
    }
}
二、线程工厂
public class MyThreadFactory implements ThreadFactory {

    private static int threadInitNumber;

    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    @Override
    public Thread newThread(Runnable r) {
        // \uD83D\uDE42 : 🙂
        // 自定义线程名
        return new Thread(r, "thread-\uD83D\uDE42-" + nextThreadNum());
    }
三、自定义拒绝策略
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {

    private static int taskNumber;

    private static synchronized void nextThreadNum() {
        taskNumber++;
    }

    /* RejectedExecutionHandler 拒绝策略提供了如下四种
     * java.util.concurrent.AbortPolicy 抛出异常
     * java.util.concurrent.CallerRunsPolicy 交给主线程执行
     * java.util.concurrent.DiscardPolicy 丢弃不做任何处理
     * java.util.concurrent.DiscardOldestPolicy 移除队列第一个任务,添加当前任务
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        nextThreadNum();
        // 在队列满时,可以自定义最大线程数
        /* if (!executor.isShutdown()) {
            if (executor.getMaximumPoolSize() < executor.getQueue().size() / 2) {
                executor.setMaximumPoolSize(executor.getMaximumPoolSize() + 1);
            }
        }*/
        // 拒绝策略抛出异常
        //throw new RejectedExecutionException("Task " + r.toString() +" rejected from " + executor.toString());
        // 模拟拒绝策略抛出异常
        System.out.println("执行" + taskNumber + "拒绝策略,抛出异常");
    }
}
四、测试

比如一次性提交了 100 个任务,按照下面的线程池参数,100 个任务是如何执行的

  • 1、首先线程池会创建 5 个线程去执行前 5 个任务
  • 2、从第六个任务开始都会放到任务队列中,即 LinkedBlockingQueue 中
  • 3、当任务队列中 60 个任务放满后,这时候未处理还剩 35 个任务,已处理 65 个(任务队列 60 个 + 在执行 5 个)
  • 4、第 65 ~ 70 个任务会直接创建执行,只能创建 5 个(最大线程数 10 - 核心线程数 5 )
  • 5、第 71 ~ 100 个任务,因为线程池满了,最大线程数 10 也满了,会进入指定的拒绝策略
public class ThreadPoolTest {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolConfig.getInstance();
        for (int i = 0; i < 100; i++) {
            threadPoolExecutor.execute(() -> {
                System.out.println("线程名:" + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        /*      统计多线程运行时长   */
        // 等待线程池中正在执行和待执行线程执行完成,再关闭线程池
        threadPoolExecutor.shutdown();
        // 立马关闭线程,不管线程池中是否有正在执行或待执行线程
        //threadPoolExecutor.shutdownNow();
        System.out.println(threadPoolExecutor.getQueue().size());
        boolean flag= true;
        while (flag) {
            // isShutDown 方法:当调用 shutdown() 或 shutdownNow() 方法后返回为 true。
            // isTerminated 方法: 当调用 shutdown() 并且所有提交的任务完成后返回为 true;
            // isTerminated 方法: 当调用 shutdownNow() 成功停止后返回为 true;
            if(threadPoolExecutor.isTerminated()){
                flag = false;
                long endTime = System.currentTimeMillis();
                System.out.println("------线程池运行时长-------"+(endTime - startTime));
            }
        }
    }
}

根据上面线程池配置以及 Thread.sleep(1000),则每个任务睡眠 1000 ms,最大线程数加上队列大小总共 70 个任务,1000 ms可执行最大线程数 10 个任务,线程池运行时长最少 7000 ms,结果如下,可以看到多线程运行时长 7169 ms
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值