还是直接上源码吧
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
上面这段代码就是Executors.newSingleThreadExecutor方法得源码,因为FinalizableDelegatedExecutorService使用的是代理模式,所以接下来再看一下ThreadPoolExecutor的构造函数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
这里有两个参数需要注意以下:corePoolSize和maximumPoolSize。看一下这两个参数的说明:
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
意思大概是说corePoolSize是线程池中的最大线程数量,而maxmumPoolSize意思是阻塞队列最大的阻塞线程数量,然后我们再回去看一下Executors.newSingleThreadService方法,给出的这两个参数都是1,那么问题来了,如果我想要搞一个只有一个运行线程的线程池时这个方法就不能满足我们的需求了,那么直接new一个ThreadPoolExecutor如:new ThreadPoolExecutor(1, 0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())可不可以呢?答案是:不可以,因为在ThreadPoolExecutor的构造函数里第一个if语句就判断了,如果maximumPoolSize <= 0就会抛出一个异常。再回来看看,如果我们使用了JDK自带的newSingleThreadPool会发生什么情况:
1. 第一次submit一个线程,因为没有在运行的线程,所以该线程不会被提交到阻塞队列里,而是直接start运行。
2. 紧接着我们再submit一个线程,这次因为已经有一个线程在运行了,并且运行的线程数量等于corePoolSize所以,这个线程会被提交到阻塞队列。
3. 再submit第三个线程,这次就是饱和策略大显身手的时候了。
What,我原本是不想让第二个线程提交的,这样不就算是重复提交了吗?对,是重复提交。所以看来自带的JDK给的线程池是不能满足需求了。下面是ThreadPoolExecutor.execute方法的部分源码,可以解释上面的分析结果:
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)