Executors工具类的内部(一)

355 阅读2分钟

Executors

线程池的工具类:

Factory and utility methods for Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes defined in thispackage. This class supports the following kinds of methods:

  • Methods that create and return an {@link ExecutorService} set up with commonly useful configuration settings.
  • Methods that create and return a {@link ScheduledExecutorService} set up with commonly useful configuration settings.
  • Methods that create and return a "wrapped" ExecutorService, that disables reconfiguration by making implementation-specific methods inaccessible.
  • Methods that create and return a {@link ThreadFactory} that sets newly created threads to a known state.
  • Methods that create and return a {@link Callable} out of other closure-like forms, so they can be used in execution methods requiring {@code Callable}.

@since 1.5

@author Doug Lea

翻译:Executors是工具类,为Executor、ExecutorService、ScheduledExecutorService、ThreadFactory、Callable类提供了静态方法。这个类支持以下方法:

  • 使用常用的配置去实例 ExecutorService 并返回其对象
  • 使用常用的配置去实例 ScheduledExecutorService 并返回其对象
  • 实例 ThreadFactory 并返回其对象, 创建出来的线程不是守护线程,并且优先等级Thread.NORM_PRIORITY

...

Executors.newFixedThreadPool(int nThread)

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>())
                                      ;
    }
核心线程数量和最大线程数量相同,说明不会开辟非核心线程

使用 LinkedBlockingQueue 这是一个大小`Integer.MAX_VALUE`的阻塞队列。 这也说明了无论怎样都不会开辟非核心线程。

但是这是非常危险的事,在高并发下随时会来上百万的任务,这样直接就 OOM 了

Executors.newSingleThreadExecutor()

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 
                                    1,
                                    0L, 
                                    TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable());
}
很明显,这用线程池创建了单线程。
而且任务队列与固定大小线程池相同,很容易 oom

Executors.newCachedThreadPool()

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 
                                      Integer.MAX_VALUE,
                                      60L,
                                      TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}
所有的线程都是非核心线程,
使用的队列是同步队列。这个队列的特点是容量只有1。
    满了的话put的线程会阻塞。
    空了的话take的线程也会阻塞。
还有一点,虽然这是队列但是得到的实例默认是一个栈
    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }
    fair默认是false

ThreadPoolExecutor

建议直接实例化 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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

主要点:任务队列和拒绝策略

BlockingQueue 的实现类主要有4个

ArrayBlockingQueue  最常使用

DelayQueue  

LinkedBlockingQueue

SynchronousQueue

根据需求使用,当然我们也可以实现BlockingQueue接口,但是略麻烦

拒绝策略 的实现了也是四个

AbortPolicy 抛出异常(默认)

CallerRunsPolicy 任务提交者自己执行

DiscardOldestPolicy 抛弃任务队列的头部任务

DiscardPolicy 什么都不做

根据需要我们也可以通过实现 RejectedExecutionHandler 接口来自定义拒绝策略。