概述
我们上篇文章讲到,Dubbo提供了多种线程模型,是为了尽早的释放I/O线程,把耗时的业务分派给业务线程池,那么这里的线程池是什么类型的线程池呢?是我们所熟知的JAVA线程池吗?并不是,这里的线程池,也是Dubbo的扩展接口ThreadPool。
ThreadPool
Dubbo为我们提供了四种类型的线程池,分别是
1、FixedThreadPool(默认),固定线程数的线程池。
2、LimitedThreadPool,线程池的线程数随着并发量动态增加,但不会超过配置的阈值。
3、EagerThreadPool,当提交的任务超过线程池的配置而触发拒绝策略后,会再次将任务投入队列。
4、CachedThreadPool,如果线程池里的线程空闲一定时间后,会回收线程。
源码分析
要了解Dubbo为我们提供了哪些线程池,我们首先要看一看ThreadPool这个扩展点接口的代码
@SPI("fixed")
public interface ThreadPool {
@Adaptive({Constants.THREADPOOL_KEY})
Executor getExecutor(URL url);
}
可以看到,该接口上的SPI注解,表明该方法是一个扩展点接口。该接口只有一个方法,getExecutor,用来获取线程池,返回Executor的实例,而这个Executor是JAVA并发包下的java.util.concurrent.Executor。
下面我们一一分析每种类型线程池的源码
FixedThreadPool类,固定数量的线程池:
public class FixedThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
// 获取线程池名字
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
// 获取线程数量
int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
// 获取等待队列大小
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}
源码很简单,通过URL参数获取创建线程池的各种参数,包括线程名字,线程数量和等待队列大小,然后通过JAVA并发包下的java.util.concurrent.ThreadPoolExecutor创建线程池。注意,线程池的corePoolSize和maximumPoolSize都是一样的哦。
LimitedThreadPool类:
public class LimitedThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
// 获取线程名
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
// 获取corePoolSize
int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
// 获取maximumPoolSize
int