Java快速手动创建线程池ThreadPoolExecutor

1,765 阅读1分钟

一、先上代码,再现场景。

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 苦力怕大囧哥
 * @version 1.0
 * @date 2020/5/6 14:27
 */
public class ThreadTest2 {
    public static void main(String[] args) {
        // 核心线程数
        int corePoolSize = 3;
        // 最大线程容量
        int maximumPoolSize = 5;
        // 线程空闲时,可存活时间
        long keepAliveTime = 10;
        // 时间单位 秒
        TimeUnit unit = TimeUnit.SECONDS;
        // 任务队列 容量
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3);
        // 线程工厂
        ThreadFactory threadFactory = new MyThreadPoolFactory();
        // 拒绝策略
        RejectedExecutionHandler rejectedExecutionHandler = new MyRejectHandler();

        // 主体 线程池执行器
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                rejectedExecutionHandler
        );

        // 创建10个任务,并加入 线程池CorePool中
        int taskLength = 10;
        for (int i = 0; i < taskLength; i++) {
            MyTask task = new MyTask(String.valueOf(i));
            threadPoolExecutor.execute(task);
        }
    }

    static class MyThreadPoolFactory implements ThreadFactory {
        private final AtomicInteger threadNum = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, "线程-" + threadNum.getAndIncrement());
            System.out.println(thread.getName() + "创建完成");
            return thread;
        }
    }

    static class MyRejectHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.out.println(r.toString() + " 已被拒绝");
        }
    }

    static class MyTask implements Runnable {
        private String name;

        public MyTask(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                // 让任务慢点,模拟当前任务占用进程
                Thread.sleep(3000);
                System.out.println(this.toString() + " 正在运行中...");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public String toString() {
            return "MyTask{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

二、总结一下

  • 调用 ThreadPoolExecutor 的execute提交线程到CorePool(这是我自定义的名字),首先检查CorePool线程数量。
  • 如果 CorePool <= corePoolSize,直接创建新线程执行任务。
  • 如果 corePoolSize < CorePool <= maximumPoolSize,根据corePoolSize线程数量创建新线程逐批次执行任务量。
  • 如果 maximumPoolSize < CorePool <= (maximumPoolSize + BlockingQueue),会直接创建最大线程量maximumPoolSize,按最大线程量逐批次执行任务
  • 如果 CorePool > (maximumPoolSize + BlockingQueue),那么超出的线程 maximumPoolSize + BlockingQueue - CorePool 执行拒绝策略。

可尝试改变上面代码的 corePoolSize, maximumPoolSize, workQueue , taskLength 的数字大小测试,查看控制台打印信息,java探索中,有问题可以指出,共同进步~