一个例子理解java线程池 ThreadPoolExecutor

创建一个线程池需要7个参数

  • corePoolSize 核心线程数量
  • maximumPoolSize 最大线程数量
  • keepAliveTime 当线程数大于核心时,这是多余空闲线程在终止之前等待新任务的最长时间
  • TimeUnit 等待时间keepAliveTime的单位
  • workQueue 任务队列类型为BlockingQueue
  • ThreadFactory 创建线程的工厂
  • RejectedExecutionHandler 线程池拒绝处理器

例子

如何理解这几个参数呢,举个栗子

       可以把线程池执行任务想象成我们去营业厅办理业务, 假设营业厅有5个窗口可以办理业务, 当同时办理业务的人多余5个的时候, 工作人员会安排剩下的人到等候厅的椅子上等候办理, 假设等候厅有20个椅子, 那么如果人多到椅子坐不下会怎么办, 营业厅会再开设5个临时窗口, 新来的人发现等候厅的椅子坐不下了, 就会去临时窗口办理, 临时窗口不会一直开设, 某个临时窗口如果发现一个小时之内都没有人来就会关闭. 还有可能人实在太多, 多到临时窗口也被占满, 这个时候新来的人就会被告知明天再来(被拒绝)

联系例子,再来看一下参数

  • corePoolSize 营业厅原本的5个窗口,它们会一直开着
  • maximumPoolSize 原本的窗口数+临时窗口数
  • keepAliveTime 某个临时窗口发现一个小时内没人来就会关闭,这个time就指这一个小时
  • workQueue 等候厅的20个椅子
  • ThreadFactory 这些窗口办理的是联通业务还移动业务有它规定
  • RejectedExecutionHandler 当临时窗口也被占满时要怎么处理, 如例子中的告知明天再来办理就是一种拒绝处理

代码

    //设置线程属性 规定窗口属性 
    ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable runnable) {
                Thread thread = new Thread(runnable);
                thread.setName("联通业务");
                return thread;
            }
        };

        //拒绝策略
        RejectedExecutionHandler handler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
                System.out.println("明天再来");
            }
        };
       
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                //corePoolSize 核心线程数 常驻窗口数(5)
                5,
                //maximumPoolSize  最大线程数 常驻窗口(5)+临时窗口(5)
                10,
                //keepAliveTime 临时窗口关闭时间(1小时)
                1L,
                //unit 单位小时
                TimeUnit.HOURS,
                //workQueue 任务队列 等候厅座位(20)
                new ArrayBlockingQueue(20),
                //threadFactory 线程工厂 规定窗口属性
                threadFactory,
                //RejectedExecutionHandler 拒绝策略
                handler
        );

测试代码

        for (int i = 1; i <= 50; i++) {
            System.out.println("第" + i + "个人来办理业务");
            threadPool.submit(() -> {
                try {
                    System.out.println(Thread.currentThread().getName()+"窗口正在办理业务");
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

            Thread.sleep(100);
        }

测试结果

第1个人来办理业务
联通业务窗口正在办理业务
第2个人来办理业务
联通业务窗口正在办理业务
第3个人来办理业务
联通业务窗口正在办理业务
第4个人来办理业务
联通业务窗口正在办理业务
第5个人来办理业务
联通业务窗口正在办理业务    ---------->前5个直接上窗口办理
第6个人来办理业务
第7个人来办理业务
第8个人来办理业务
......
第25个人来办理业务
第26个人来办理业务        ---------->20个被安排在等候厅
联通业务窗口正在办理业务
第27个人来办理业务
联通业务窗口正在办理业务
第28个人来办理业务
联通业务窗口正在办理业务
第29个人来办理业务
联通业务窗口正在办理业务
第30个人来办理业务
联通业务窗口正在办理业务
第31个人来办理业务       ---------->开设5个临时窗口办理
明天再来
第32个人来办理业务
明天再来
......
第50个人来办理业务
明天再来                ---------->被拒绝     

其它

线程池的一些其它注意点,任务队列,常用四种线程池,合理配置等可参看一个大佬的文章

由浅入深理解Java线程池及线程池的如何使用

转载请注明出处

你可能感兴趣的:(一个例子理解java线程池 ThreadPoolExecutor)