终于讲到Executors来了,学习并发这个系列的最初目的也是为了更好的了解Executors这个类的使用方法。
首先说说这个类是干嘛的。
这个类充斥了无数的静态方法,也就是说,这个类里面大部分的方法都是可以直接通过类名调用的,所以很显然这是一个工具类了,先感受下这个工具类
new开头的方法就有这么多,这些方法主要都是创建线程池的,但是我并不会讲完所有的new系列的方法,我会将我们熟悉的方法。
什么叫我们熟悉的方法呢,就是只要一看源码,你就什么都知道了的意思。
今天我要讲以下4个方法:
上图就是我要讲解的4个方法,截图的目的是为了让大家可以方便的看到方法里面的参数的含义。
注意:图中的参数我是乱填的,纯粹为了简洁,大家不可照着图中的示例参数填写。
我们来学习第一个方法,直接看这个函数的源码,相信你一定能知道这个函数是干嘛的了。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
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<Runnable>());
}
看看这个队列,现在换成了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 返回的线程池对象的弊端如下:
- FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。- CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。