线程池的源码解析 jdk1.8

线程池

三大方法

newSingleThreadExecutor方法

线程池三大方法指的是线程池工具类Executors的三个创建线程池的方法,而newSingleThreadExecutor是其中一个,创建一个只有一个线程的线程池

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

通过上面的源代码我们发现这个方法调用了一个ThreadPoolExecutor方法,这个方法是创建线程池的原生方法,在阿里开发手册中建议我们都使用ThreadPoolExecutor方法,而不要去使用Executors工具类中的方法,因为工具类中的线程池可能存在安全隐患。

newFixedThreadPool方法

Executors中创建一个固定线程池大小的方法

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

newCachedThreadPool方法

Executors中创建一个一个可伸缩大小的线程池,在这个方法中调用的ThreadPoolExecutor方法关于最大线程数使用的是Integer.MAX_VALUE,十分的不安全,故不建议使用这个方法

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

七大参数

在Executors中三个创建线程池的方法其实都调用了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;
    }
  1. int corePoolSize 线程池的核心线程数,不管多少线程调用了线程池开启线程,即使没有核心线程数量的线程也会被一直开启
  2. int maximumPoolSize 最大线程数,即包括核心线程数在内可以开启的最大的线程数
  3. long keepAliveTime 除了核心线程数之外的线程,保持空闲的最大时间数量,如果超过这个数量,空闲线程池会被关闭
  4. TimeUnit unit 超时等待即上一个保持空闲时间数量的单位
  5. BlockingQueue<Runnable> workQueue 阻塞队列,如果超过这个阻塞队列长度的线程在等待,则会开启核心线程以外的其他线程。例如,有两个核心线程,已经在工作,而阻塞队列的长度是3,当有三个以内的线程在等待被开启时,则会处于阻塞队列当中,当有超过阻塞队列长度的线程在等待,例如有4个在等待,超过阻塞队列的长度3,超过1,则会开启核心线程以外的线程一个,如果超过两个则开启两个,直到达到最大线程数。
  6. ThreadFactory threadFactory 线程工厂,简单说是用来创建线程使用的,ThreadFactory里面只有newThread这个方法, Executors.defaultThreadFactory()是Executors类中使用的默认的线程工厂。
  7. RejectedExecutionHandler handler ,拒绝策略,当已经开启了最大线程数并且阻塞队列以满时,会采取一种拒绝策略,而这四种拒绝策略JDK已经帮我们定义好了,我们去使用就可以了。defaultHandler是Executors中使用的默认的拒绝策略 AbortPolicy()

四种拒绝策略

在这里插入图片描述

RejectedExecutionHandler handler是一个接口,而这个接口有四个实现类

AbrotPolicy拒绝策略

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());
    }
}

所有的拒绝策略都只会在已经开启最大线程数并且阻塞队列以满时执行,而我们可以在源码的注释中看见这么一句话Always throws RejectedExecutionException.这句话的意思就是当执行拒绝策略时总是会抛出异常并且不处理这一个线程。

CallerRunsPolicy拒绝策略

public static class CallerRunsPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code CallerRunsPolicy}.
     */
    public CallerRunsPolicy() { }

    /**
     * Executes task r in the caller's thread, unless the executor
     * has been shut down, in which case the task is discarded.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

CallerRunsPolicy这句话的意思是当执行拒绝策略时,让要求开启这个线程的线程来执行这个线程,例如main线程调用,则会返回让main线程来执行这个线程。当然这样也就不会抛出异常了。

DiscardPolicy拒绝策略

public static class DiscardPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardPolicy}.
     */
    public DiscardPolicy() { }

    /**
     * Does nothing, which has the effect of discarding task r.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}

什么也不做,这就产生了丢弃任务r的效果。并且不抛出异常。

DiscardOldestPolicy拒绝策略

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardOldestPolicy} for the given executor.
     */
    public DiscardOldestPolicy() { }

    /**
     * Obtains and ignores the next task that the executor
     * would otherwise execute, if one is immediately available,
     * and then retries execution of task r, unless the executor
     * is shut down, in which case task r is instead discarded.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}

此种策略是一种DiscardPolicy策略的升级版,除了拥有DiscardPolicy的特性,DiscardOldestPolicy还会尝试去和最早的竞争。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值