我是靠谱客的博主 从容白云,最近开发中收集的这篇文章主要介绍阿里规约---为什么建议使用ThreadPoolExecutor自定义线程池创建线程池的四种方式newSingleThreadExecutor()newFixedThreadPool(int nThreads)newCachedThreadPool()newScheduledThreadPool(int corePoolSize),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

创建线程池的四种方式

newSingleThreadExecutor 创建一个拥有一个线程的线程池,该线程池的优点是保证事件的执行顺序(先进先出队列(FIFO)、后进先出(LIFO))

newFixedThreadPool(int nThreads) 创建一个定长线程池,传进去的参数为可同时并发的线程数,超出的任务放进阻塞队列

newScheduledThreadPool(int corePoolSize) 创建一个定长的能执行周期任务的线程池

newCachedThreadPool() 创建可以缓存的线程池,若是事件数小于线程池内线程数,则jvm可回收,反之再创建线程

我们先来看看创建线程池内的构造参数

在这里插入图片描述
corePoolSize:线程池的基本大小(核心线程数)

maximumPoolSize:最大线程数(非核心线程数)

keepAliveTime:线程保持时长,设置线程过期时间

TimeUnit unit:时长单位(TimeUnit.MILLISECONDS、TimeUnit.SECONDS)

workQueue:工作队列

defaultHandler:拒绝策略

下面我们来给大家展开讲每一种线程池的优缺点

newSingleThreadExecutor()

我们先来看看newSingleThreadExecutor()的源码
在这里插入图片描述
从上面的源码我们可以看出,核心线程数为1、最大线程数也为1,所以执行任务时只是一个线程去执行,剩下的加入工作队列,比如我过来了50个任务,只能一个个的去执行,能保证任务的执行顺序,但是执行效率没有其它的线程池高,我们来看看该线程池的结构图

在这里插入图片描述

newFixedThreadPool(int nThreads)

在这里插入图片描述
传进去的int nThreads,是核心线程数,也是最大线程数,线程池结构图
在这里插入图片描述

我们来着重看看这个LinkedBlockingQueue工作队列,先看看它的源码
在这里插入图片描述
它是一个无界队列,也就是说无论多少任务我都照单全收,但是这非常的危险,因为可能会由于线程阻塞等原因,任务执行的慢,可能会造成OOM

newCachedThreadPool()

先来看看源码和结构图,我们从源码结合结构图来分析
在这里插入图片描述
在这里插入图片描述
看着源码和结构图我们能明白,核心线程数为0,来的所有任务会直接塞进阻塞队列(SynchronousQueue)中,什么是阻塞队列呢?看到上面的结构图,阻塞队列只有一个,也就是说有一个任务到阻塞队列中,线程池得立马起一个线程去响应它,要不然它会一直阻塞在队列中,别的任务进不来

newScheduledThreadPool(int corePoolSize)

在这里插入图片描述
调用newScheduledThreadPool(int corePoolSize)的方法时也就会直接调用父类创造线程池的方法,也就是我们下面的这个基本的方法,为什么它可以定时执行呢?最主要还是在它的队列上,new DelayedWorkQueue()
在这里插入图片描述
new DelayedWorkQueue()是一个延时队列,可以根据设置的延时时间取到队列中任务,然后启动线程执行,实现定时执行的效果

现在我们回归正题,为什么java给了我们这么方便使用线程池的方式,阿里还不推荐使用呢?

我们回过头来看看,在newSingleThreadExecutornewFixedThreadPool(int nThreads)使用到的队列,它是一个无界队列啊,我如果有10000W个任务呢???我的天,JVM都快哭了吧,所以说当线程数过多时,没有做到一个很好的限制,全部都往队列里加容易造成OOM,这在正式环境中是一个致命的问题

newScheduledThreadPool(int corePoolSize)newCachedThreadPool()这两个呢?我们来看看它的maximumPoolSize,都为Integer.MAX_VALUE,这样会有一个问题,我还是10000W个任务,我就会起10000W个线程来执行,这都能把电脑的CPU干着火了都

一个是对内存的消耗,还有一个是让CPU的负载过重,所以阿里不推荐这四种创建线程池的方式

阿里支持的是自定义线程的创建,我上代码给大家看看怎么自定义线程
在这里插入图片描述
所以要根据实际任务来自定义线程池,就不会出现上面那四种常规方法创建线程池所出现的问题,但是!!
在这里插入图片描述
有一个小问题,我用一幅图给大家描述一下,最坏的情况
在这里插入图片描述

还有十个任务呢?它们去哪了?我直接说了吧,它会直接报错,这就要涉及到一个知识点了,拒绝策略(ThreadFactory)

举个栗子

public class thread {
    public static void main(String[] args) {

        ExecutorService self = new ThreadPoolExecutor(
                10,
                20,
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(20));
        for(int i = 50;i<100;i++){
            self.execute(new MyThread());
        }
    }

}
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(MyThread.currentThread());
    }
}

执行结果:
在这里插入图片描述
会报错,这就是拒绝策略的作用,当我们自定义的线程池接收不了这个任务时,会直接抛出异常,关于里面的源码我就不细讲了,感兴趣的同学可以在下面评论催催更,说不定明天我就更新了呢

在这里插入图片描述
谢谢你们的阅读,给个赞赞赞赞赞来鼓励我吧

完成:TO: 2021/3/30 16:47

最后

以上就是从容白云为你收集整理的阿里规约---为什么建议使用ThreadPoolExecutor自定义线程池创建线程池的四种方式newSingleThreadExecutor()newFixedThreadPool(int nThreads)newCachedThreadPool()newScheduledThreadPool(int corePoolSize)的全部内容,希望文章能够帮你解决阿里规约---为什么建议使用ThreadPoolExecutor自定义线程池创建线程池的四种方式newSingleThreadExecutor()newFixedThreadPool(int nThreads)newCachedThreadPool()newScheduledThreadPool(int corePoolSize)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部