dubbo中的线程池

dubbo提供了四种线程池。其实我理解还是还是根据ThreadPoolExecutor这个JDK提供的线程池类,只不过适应性的改变了其中的参数。dubbo分别提供了1. 缓存线程池 2。固定大小线程池 3. 上届线程池 4.定时线程池。下面具体的说一说这些线程池。

1. 公共行为

首先这些线程池类均继承了ThreadPool接口。该接口中的定义了getExecutor

/**
 * Thread pool
 *
 * @param url URL contains thread parameter
 * @return thread pool
 */
@Adaptive({THREADPOOL_KEY})
Executor getExecutor(URL url); // 实际上还是对JDKExcutor的封装

  可以看到其返回值还是Executor。并且需要采用什么样的线程池,可以从URL中进行设置。

2. CachedThreadPool

public class CachedThreadPool implements ThreadPool {

    // 可以看到这里设置了alive这个参数
    // 那么也就是说用这个存活时间来控制整个线程池的时间
    @Override
    public Executor getExecutor(URL url) {
        String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
        int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS);
        int threads = url.getParameter(THREADS_KEY, Integer.MAX_VALUE);
        int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
        int alive = url.getParameter(ALIVE_KEY, DEFAULT_ALIVE);
        return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
                queues == 0 ? new SynchronousQueue<Runnable>() :
                        (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                : new LinkedBlockingQueue<Runnable>(queues)),
                new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
    }
}

 从源码中可以看到,将队列设置为同步队列,只要没有没有达到threads的数量,就会一直增加线程。

3.FixedThreadPool

public class FixedThreadPool implements ThreadPool {

    // 开启固定大小的线程数
    // 就是将核心池以及最大池大小都调整为一致。同时阻塞队列设置为同步队列
    @Override
    public Executor getExecutor(URL url) {
        String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
        int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
        int queues = url.getParameter(QUEUES_KEY, 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));
    }

}

  固定大小线程池,顾名思义就是线程池中的线程数量维持着固定大小。其原理就是将其中的队列设置为同步队列,同时将最大池和核心池的数量都设定为一致就行。

4. LimitedThreadPool

public class LimitedThreadPool implements ThreadPool {

    // 如果queue == 0 则创建同步队列
    // queue < 0 就创建无界队列
    // queue > 0 就创建上届队列

    // 可扩张线程池,就是把阻塞队列改成同步队列。这样有任务的时候就会一直开辟新的线程
    @Override
    public Executor getExecutor(URL url) {
        String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
        int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS);
        int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
        int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
        return new ThreadPoolExecutor(cores, threads, Long.MAX_VALUE, TimeUnit.MILLISECONDS,
                queues == 0 ? new SynchronousQueue<Runnable>() :
                        (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                : new LinkedBlockingQueue<Runnable>(queues)),
                new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
    }
}  


顾名思义,可扩张线程池就是通过上届队列存储任务。

4.EagerThreadPoolExecutor
public class EagerThreadPoolExecutor extends ThreadPoolExecutor {

    /**
     * task count
     */
    private final AtomicInteger submittedTaskCount = new AtomicInteger(0);

    public EagerThreadPoolExecutor(int corePoolSize,
                                   int maximumPoolSize,
                                   long keepAliveTime,
                                   TimeUnit unit, TaskQueue<Runnable> workQueue,
                                   ThreadFactory threadFactory,
                                   RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    /**
     * @return current tasks which are executed
     */
    public int getSubmittedTaskCount() {
        return submittedTaskCount.get();
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        submittedTaskCount.decrementAndGet();
    }

    @Override
    public void execute(Runnable command) {
        if (command == null) {
            throw new NullPointerException();
        }
        // do not increment in method beforeExecute!
        submittedTaskCount.incrementAndGet();
        try {
            super.execute(command);
        } catch (RejectedExecutionException rx) {
            // retry to offer the task into queue.
            final TaskQueue queue = (TaskQueue) super.getQueue();
            try {
                if (!queue.retryOffer(command, 0, TimeUnit.MILLISECONDS)) {
                    submittedTaskCount.decrementAndGet();
                    throw new RejectedExecutionException("Queue capacity is full.", rx);
                }
            } catch (InterruptedException x) {
                submittedTaskCount.decrementAndGet();
                throw new RejectedExecutionException(x);
            }
        } catch (Throwable t) {
            // decrease any way
            submittedTaskCount.decrementAndGet();
            throw t;
        }
    }
}

  

这个池子的比较不同的是:还是通过ThreadPoolExecutor实现任务的管理,唯一不同的是当任务执行失败的时候,会将任务存储到自定义的taskqueue中。同时维持这一个当前池子的任务的计数。
线程池中的所有核心线程都在忙碌时,此时如果再添加新的任务不会放入阻塞队列,而且创建新的线程,直到达到最大线程限制,此时如果还有任务,才会放入阻塞队列。

posted @ 2020-07-13 00:21  知事  阅读(1411)  评论(0编辑  收藏  举报