• 面试题: 线程池的核心参数


    目的

    面试复习方便, 个人学习笔记

    资源

    B站的一个讲高频面试题的一个学习视频

    核心参数

    在这里插入图片描述

    corePoolSize 核心线程数目

    • 最多保留的线程数

    maximumPoolsize 最大线程数

    • 核心线程 + 救急线程

    keepAliveTime 生存时间

    • 针对救急线程的存活时间

    unit 时间单位

    • 针对救急线程的存活时间

    workQueue

    • 阻塞队列

    threadFactory 线程工厂

    • 可以为线程创建时起个好名字

    handler拒绝策略

    • 四种(第二个实现不是TreadPoolExecutor里面的, 是一个三方工具类里实现的)
      -

    java.util.concurrent.ThreadPoolExecutor.AbortPolicy

        public static class AbortPolicy implements RejectedExecutionHandler {
            public AbortPolicy() { }
    
    		// 直接抛出异常
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                throw new RejectedExecutionException("Task " + r.toString() +
                                                     " rejected from " +
                                                     e.toString());
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy

        public static class CallerRunsPolicy implements RejectedExecutionHandler {
            public CallerRunsPolicy() { }
    		
    		// 线程池资源用完了, 调用者自己去执行
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    r.run();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    java.util.concurrent.ThreadPoolExecutor.DiscardPolicy

        public static class DiscardPolicy implements RejectedExecutionHandler {
    
            public DiscardPolicy() { }
    
    		// 啥也不干, 也是一种策略
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

        public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    
            public DiscardOldestPolicy() { }
    
    		// 最旧的抛弃掉
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    e.getQueue().poll();
                    e.execute(r);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试代码

    /**
     * 线程池学习
     *
     * @author xiaozhengN 571457082@qq.com
     * @since 2022-10-19 22:39:13
     **/
    @Slf4j
    public class TestThreadPoolExecutor {
        public static void main(String[] args) {
            AtomicInteger atomicInteger = new AtomicInteger(1);
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                    2,
                    3,
                    0,
                    TimeUnit.MICROSECONDS,
                    new ArrayBlockingQueue<>(2),
                    r -> new Thread(r, "myThread" + atomicInteger.getAndIncrement()),
                    new ThreadPoolExecutor.DiscardOldestPolicy()
            );
            showState(threadPool);
            threadPool.submit(new MyTask("1", 3600000));
            showState(threadPool);
            threadPool.submit(new MyTask("2", 3600000));
            showState(threadPool);
            threadPool.submit(new MyTask("3"));
            showState(threadPool);
            threadPool.submit(new MyTask("4"));
            showState(threadPool);
            threadPool.submit(new MyTask("5", 3600000));
            showState(threadPool);
            threadPool.submit(new MyTask("6"));
            showState(threadPool);
        }
    
        // 获取线程池核心线程数和阻塞队列信息
        private static void showState(ThreadPoolExecutor threadPool) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            List<Object> blockingQueueList = new ArrayList<>();
            for (Runnable runnable : threadPool.getQueue()) {
                try {
                    Field callable = FutureTask.class.getDeclaredField("callable");
                    callable.setAccessible(true);
                    Object adapter = callable.get(runnable);
                    Class<?> clazz = Class.forName("java.util.concurrent.Executors$RunnableAdapter");
                    Field task = clazz.getDeclaredField("task");
                    task.setAccessible(true);
                    Object o = task.get(adapter);
                    blockingQueueList.add(o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
             log.debug("pool size: {}, queue: {}", threadPool.getPoolSize(), blockingQueueList);
        }
    
        static class MyTask implements Runnable {
            private final String name;
            private final long duration;
    
            public MyTask(String name) {
                this(name, 0);
            }
    
            public MyTask(String name, long duration) {
                this.name = name;
                this.duration = duration;
            }
    
            @Override
            public void run() {
                try {
                    log.debug("running...name: {}, obj: {}", Thread.currentThread().getName(), this);
                    Thread.sleep(duration);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public String toString() {
                return "MyTask(" + name + ")";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    日志:

    2022-10-19 23:39:25,336 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 0, queue: []
    2022-10-19 23:39:25,337 DEBUG [main.daily.TestThreadPoolExecutor] - running...name: myThread1, obj: MyTask(1)
    2022-10-19 23:39:25,637 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 1, queue: []
    2022-10-19 23:39:25,637 DEBUG [main.daily.TestThreadPoolExecutor] - running...name: myThread2, obj: MyTask(2)
    2022-10-19 23:39:25,937 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 2, queue: []
    2022-10-19 23:39:26,238 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 2, queue: [MyTask(3)]
    2022-10-19 23:39:26,538 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 2, queue: [MyTask(3), MyTask(4)]
    2022-10-19 23:39:26,538 DEBUG [main.daily.TestThreadPoolExecutor] - running...name: myThread3, obj: MyTask(5)
    2022-10-19 23:39:26,839 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 3, queue: [MyTask(3), MyTask(4)]
    2022-10-19 23:39:27,139 DEBUG [main.daily.TestThreadPoolExecutor] - pool size: 3, queue: [MyTask(4), MyTask(6)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    2022年面试复盘大全500道:Redis+ZK+Nginx+数据库+分布式+微服务
    设计模式之原型模式
    PDF怎么转图片?四种转换方法分享
    [算法刷题笔记]二叉树练习(1)二叉树的镜像
    【linux网络编程】阻塞、非阻塞、同步、异步
    JavaScript 70 JavaScript Ajax 70.4 AJAX - 服务器响应
    Spring高手之路10——解锁Spring组件扫描的新视角
    多线程与高并发(二)—— Synchronized 加锁解锁流程
    Altium Designer
    docker定期清理无用镜像
  • 原文地址:https://blog.csdn.net/xiaozhengN/article/details/127417476