并发学习计划-了解Executors创建线程池的部分方法07

终于讲到Executors来了,学习并发这个系列的最初目的也是为了更好的了解Executors这个类的使用方法。

首先说说这个类是干嘛的。

这个类充斥了无数的静态方法,也就是说,这个类里面大部分的方法都是可以直接通过类名调用的,所以很显然这是一个工具类了,先感受下这个工具类


并发学习计划-了解Executors创建线程池的部分方法07_第1张图片
Executors.jpg

new开头的方法就有这么多,这些方法主要都是创建线程池的,但是我并不会讲完所有的new系列的方法,我会将我们熟悉的方法。

什么叫我们熟悉的方法呢,就是只要一看源码,你就什么都知道了的意思。

今天我要讲以下4个方法:


并发学习计划-了解Executors创建线程池的部分方法07_第2张图片
newThreadPool.jpg

上图就是我要讲解的4个方法,截图的目的是为了让大家可以方便的看到方法里面的参数的含义。

注意:图中的参数我是乱填的,纯粹为了简洁,大家不可照着图中的示例参数填写。

我们来学习第一个方法,直接看这个函数的源码,相信你一定能知道这个函数是干嘛的了。

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }

LOOK!里面居然用到了ThreadPoolExecutor,还记得我在这篇文章《通俗理解ThreadPoolExecutor》中讲过ThreadPoolExecutor吗,没看过这篇文章的赶紧去速读一篇,不然下面我讲的东西你会觉得莫名其妙。

用到了ThreadPoolExecutor,我们看看源码中是怎么填写参数的,0、MAX、60L、SECONDS、SynchronousQueue,队列居然用的是SynchronousQueue同步队列,我在这篇文章《SynchronousQueue》中讲过同步队列,没看过的也去看看,文章很短。要不了一分钟就可以看完。

我们来根据这些参数来套超市的例子。

那这个方法就是这样的:
超市有Integer.MAX_VALUE个收银台,最开始没有收银员,排队也只允许排一个,收银员闲置时间超过60秒,就会离开。

所以这其实可以容纳无限的任务,指定了运行收银台的数量,永远不会出现任务溢出的情况

这个方法说清楚了,newCachedThreadPool(ThreadFactory threadFactory)这个方法也就不必说了,无非就是自定义如何创建线程。

现在来看看这个方法

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue());
    }

看看这个队列,现在换成了LinkedBlockingQueue,而且也没有指定容量大小,所以这个队列可以容下无数的顾客,也就是容量变成了虚拟机内存大小了。

然后参数指定了有多少个收银员和收银台,那就永远不会出现任务溢出的情况了。

newFixedThreadPool(int nThreads, ThreadFactory threadFactory)这个方法也就没有必要讲了吧。

到此这4个方法就算讲完了,其他的使用方式也就没有必要讲了。

不过为了负责,这里还是贴一下文档的话:

newCachedThreadPool()
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。

newCachedThreadPool(ThreadFactory threadFactory)
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们,并在需要时使用提供的 ThreadFactory 创建新线程。

newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。

newFixedThreadPool(int nThreads, ThreadFactory threadFactory)`
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,在需要时使用提供的 ThreadFactory 创建新线程

最后在加一点友情提示,在阿里巴巴Java开发手册中,并不推荐直接使用Executors,原文如下:

线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样
的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool:
    允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
  2. CachedThreadPool 和 ScheduledThreadPool:
    允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

你可能感兴趣的:(并发学习计划-了解Executors创建线程池的部分方法07)