手动实现线程池 ThreadPool

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动实现线程池 ThreadPool相关的知识,希望对你有一定的参考价值。

Executors提供了三个经典的线程池创建方式

ExecutorService threadPool = Executors.newFixedThreadPool(int)

ExecutorService threadPool = Executors.newSingleThreadPool()
ExecutorService threadPool = Executors.newCachedThreadPool(int)

那我们在工作中到底用哪一个呢?

答案是我们在生产上只能用自定义的

技术图片

根据图中我们可以发现他们得底层实现都是用了ThreadPoolExecutor,然而第五个参数使用到的阻塞队列默认值是Integer.MAX_VALUE,也就是

2147483647,这样就相当于是一个无界的队列。所有的请求都往里塞,最终造成OOM。

根据阿里编码规范也可以看出

技术图片

参数说明

线程池底层实现的7大参数
1.corePoolSize:线程池中的常驻核心线程数
2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
3.keepAliveTime:多余的空闲线程的存活时间
4.unit:keepAliveTime的单位
5.workQueue:任务队列,被提交但尚未被执行的任务。
6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认
7.handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数

工作原理

线程池的底层工作原理
core基本线程数,当线程数大于corePoolSize时,多余线程将转入阻塞队列,阻塞队列也满了之后
将扩容到maximumPoolSize数。maximumPoolSize也满了之后将采取拒绝策略。
当线程数小了之后,根据设定的空闲线程存活时间将线程总容量回缩到corePoolSize

手动实现

/**
* 线程池demo
* @author t
* 实际工作中对多线程的使用都是线程池,不会显示的创建线程
* 而使用传统方式的方法创建线程池容易造成oom
*/
public class ThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                1,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i = 1; i <= 10; i++) {
                final int num = i;
                threadPool.execute(() -> {
                    //打印当前线程名称
                    //暂停一会线程
                    System.out.println("序号 "+num+"  "+Thread.currentThread().getName()+" 办理业务");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

运行结果

技术图片

注意:根据机器配置不同运行效果也不同,本来应该是超过最大线程数(maximumPoolSize+队列大小)就会触发拒绝策略,但是由于机器处理速度

能够处理的过来,所以没有报错。

线程暂停1秒,9个线程的运行结果

技术图片

 

作者:ushowtime

原文地址:https://www.ushowtime.cn/blog/p/50

以上是关于手动实现线程池 ThreadPool的主要内容,如果未能解决你的问题,请参考以下文章

突然想看看线程池

自己实现一个简单的线程池

简单实现java线程池

线程池

线程池

Java 线程池手动配置ThreadPoolExecutor