代码改变世界

线程池ThreadPoolExecutor

2022-12-11 23:45  杭伟  阅读(119)  评论(0编辑  收藏  举报

回顾Java创建线程的几种方式

1,继承Thread(实际Thread也是实现Runnable接口);

2,实现Runnable接口;

3,实现Callable接口(返回值);

4,由线程池创建。

 

根据阿里巴巴Java开发手册,关于并发编程有两个强制要求:

1.线程资源必须通过线程池提供,不允许在应用中自行显示创建线程。

2.线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,规避资源耗尽风险。

解释:

第1点好理解,线程的创建,挂起,唤醒都会引起线程内核态和用户态的切换,频繁的创建会导致“过度切换”问题。

第2点,先来看看Executors创建线程池的方式:

 

newFixedThreadPool

 newSingleThreadExecutor

newFixedThreadPool和newSingleThreadExecutor的核心线程数和最大线程数都是(传参)常量,但是它们的等待队列都用了LinkedBlockingQueue,

这是一个线程安全的单向链表队列,但是队列长度就趋于无界(也有人叫无界队列)。实际应用中很可能会造成任务积压,进而导致OOM。

 

newCachedThreadPool

 newScheduledThreadPool

newCachedThreadPool和newScheduledThreadPool就更加直观,允许的最大线程数为Int的最大值,生产中可能会因创建大量线程导致OOM。

故阿里巴巴强制不允许使用Executors创建线程池。

另外,这四种通过Executors创建线程池的方式,底层都是通过new ThreadPoolExecutor(...)的方式,故而,

推荐,直接使用new ThreadPoolExecutor()的方式创建线程池,或者继承ThreadPoolExecutor类来自定义线程池。

比如github有名的hippo4j项目,ExtensibleThreadPoolExecutor

 

 就是通过继承ThreadPoolExecutor的方式,自定义线程池。

 

ThreadPoolExecutor的使用

 创建线程池:

/**
         * 1 核心线程数
         * 2 最大线程数
         * 3 非核心线程空闲时的存活时间
         * 4 时间单位
         * 5 阻塞队列
         * 6 线程工厂
         * 7 拒绝策略
         **/
        ExecutorService es = new ThreadPoolExecutor(10, 50,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread();
                t.setName("ceshi1");
                return t;
            }
        }, new ThreadPoolExecutor.AbortPolicy());

线程池的5种状态:

 

状态说明:

RUNNING:能够接收新任务以及完成现有任务

SHUTDOWN:不接收新任务,但会继续处理现有任务(包括正在进行的任务和阻塞队列中的任务)

STOP:严重,不接收新任务,现有任务也会中断(也包括丢弃阻塞队列中的任务)

TIDYING:线程池即将被销毁的中间状态

TERMINATED:线程池彻底终止。

 

ThreadPoolExecutor的原理

 

线程复用原理

 

 通过while循环不停的从阻塞队列中获取任务来执行,线程和任务已解耦,

 

何时将设定的核心线程数建满?

假设我们的主代码在并发环境下,会有超过2个以上的并发请求在调用execute,

 对于每一个请求,都会通过addWorker方法创建一个线程,直到总的线程数达到核心线程数为止。

 corePoolSize用volatile修饰,对多线程是可见的。

比如创建了10个核心线程的线程池,需要通过并发工具来模拟这个情况,否则单机模拟不出这个情况。