线程池源码解析

1、通过Executors创建线程池的四种方式

1)创建单个线程的线程池

该线程池使用单个线程在无界工作队列中执行任务,如果此单个线程在执行过程中由于故障而终止,则会分配一个新的线程来执行后续的任务。工作列队中的任务保证按顺序执行,并且保证在任意时刻都不会有多个任务处于活动状态。与newFixedThreadPool(1)返回的执行器不同,newSingleThreadExecutor()不允许重新配置线程数以使用多个线程。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

2)创建指定线程数的线程池

线程池在无界队列中运行固定数量的线程来执行任务,任何时候活跃的执行任务数都跟分配的固定数量线程数相等,如果所有线程都处于活跃状态,那么新提交的任务会在队列中等待,直到有线程可用。如果有线程在执行过程中由于失败而终止,那么会有新的线程来代替它。池中的线程会一直存在,直到它显式关闭。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

3)创建可缓存线程的线程池

该线程池根据需要创建新线程,如果有任务需要执行时,会优先分配以前创建的空闲线程,没有的空闲线程的时候才会创建新线程到池中执行任务。通常可以提高执行许多短期异步任务的程序的性能。超过60秒未使用的线程会被终止并从缓存中删除,因此空闲时间足够长的池不会消耗任何资源。

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

4)创建可调度线程池

该线程池可以延时或定期执行任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
2、ThreadPoolExecutor构造器
public ThreadPoolExecutor(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue,
                            ThreadFactory threadFactory,
                            RejectedExecutionHandler handler) {

Executors的工厂方法创建的线程池底层都是通过ThreadPoolExecutor来创建的,这个构造器的每个参数定义了每个线程池的工作特性。

corePoolSize:线程池中保留的核心线程数,即使处于空闲状态,除非设置了threadPoolExecutor.allowCoreThreadTimeOut(true);

maximumPoolSize:线程池中允许的最大线程数

keepAliveTime:当线程数大于核心数时,多余的空闲线程在终止前等待新任务的最长时间

unit:keepAliveTime的时间单位

workQueue:用于执行任务之前保存任务的阻塞队列,这个队列只会保存通过execute提交的Runnable任务

threadFactory:线程池创建新线程时的线程工厂

handler:拒绝执行器,用于任务达到线程边界和队列容量而拒绝执行的处理器

3、newSingleThreadExecutor

1)底层通过ThreadPoolExecutor创建,再由FinalizableDelegatedExecutorService封装,FinalizableDelegatedExecutorService的父类是DelegatedExecutorService,他们两个都是Executors的静态内部类,所以是没有allowCoreThreadTimeOut方法来让核心线程回收,并且也无法通过setCorePoolSize(int corePoolSize)方法来重新设置核心线程数的。

static class FinalizableDelegatedExecutorService
        extends DelegatedExecutorService {
        FinalizableDelegatedExecutorService(ExecutorService executor) {
            super(executor);
        }
        protected void finalize() {
            super.shutdown();
        }
    }

2)默认核心线程数和最大线程数都是1,线程空闲最大时间为0,因为没有最大线程和核心线程一致,所以没有多余的超出核心线程数的空闲线程,默认配置的工作队列是LinkedBlockingQueue,没有指定容量默认最大值为Integer.MAX_VALUE。线程工厂和拒绝处理器使用的是默认的。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

// 底层调用的构造器是下面这个
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

3)默认线程工厂是Executors的静态内部类,创建默认线程工厂构造器

DefaultThreadFactory() {
    SecurityManager s = System.getSecurityManager();
    group = (s != null) ? s.getThreadGroup() :
                          Thread.currentThread().getThreadGroup();
    namePrefix = "pool-" +
                  poolNumber.getAndIncrement() +
                 "-thread-";
}

4)默认任务拒绝执行器是ThreadPoolExecutor的静态静态内部类,默认策略是当任务超过线程池的最大线程数量和工作队列的容量时,默认会抛出RejectedExecutionException异常。

public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

5)RejectedExecutionHandler的所有实现

当任务数量超过最大线程数和工作列队容量时,各个拒绝处理器实现类的拒绝策略如下:

AbortPolicy :抛出RejectedExecutionException异常

CallerRunsPolicy:直接使用调用execute方法的线程来执行任务,除非线程池关闭,此时任务会丢弃

DiscardOldestPolicy:丢弃最早未被执行的任务,放入新添加的任务到工作队列中,除非线程池关闭,此时任务会丢弃

DiscardPolicy:直接丢失当前被拒绝任务。

tips:除了使用JDK提供的四种自带的拒绝策略,也可以添加自定义的实现来作为任务拒绝执行策略。

4、newFixedThreadPool

看源码可以知道核心线程数和最大线程数都是传入的nThreads数量,其他配置是跟newSingleThreadExecutor一样的

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
5、newCachedThreadPool

1)核心线程数量为0,最大线程数为Integer.MAX_VALUE

2)当有新任务执行时,如果没有空闲线程,则会创建新线程执行

3)如果线程执行完任务超过60秒没有新的任务执行,那么线程会被终止回收

4)工作队列不同上面的线程池是使用的SynchronousQueue,不同于LinkedBlockingQueue底层依赖ReentranLock(内部的静态内部类Sync实现AQS,即AbstractQueuedSynchronizer),SynchronousQueue是无缓冲等待队列,内部没有容量,每个插入操作都必须等待另一个线程执行相应的删除操作,而且必须等队列中的元素被消费后才能继续添加新的元素。

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
6、newScheduledThreadPool

1)使用ScheduledThreadPoolExecutor来创建线程池,实际上还是使用父类ThreadPoolExecutor

2)不同的是工作队列使用的是DelayedWorkQueue,是ScheduledThreadPoolExecutor的静态内部类,是专用的延迟队列。

3)DelayedWorkQueue基于堆结构的等待队列

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值