初识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.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  • int corePoolSize 线程池基本大小
线程池的基本大小也就是线程池的目标大小,即在没有任务执行时线程池的大小(值得注意的是,在线程池创建初期,线程并不会立即启动,而是在有任务提交时才会启动新的线程,如果需要,可以调用prestartAllCoreThreads()方法立即启动相应数量的基本线程。),并且只有在工作队列满了的情况下才会创建出超出这个数量的线程。
 public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }
  • int maximumPoolSize 线程池最大大小
只有在工作队列满了的情况下才会创建出超出基本大小数量的线程,如果当前工作队列已满且启动线程数==maximumPoolSize时提交了新的任务,则会将其提交到RejectedExecutionHandler,执行饱和策略。
  • long keepAliveTime, TimeUnit unit 活跃时间及单位
如果某个线程的空闲时间超过了存活时间,那么将会被标记为可回收的,并且如果前线程池的大小超过基本大小时,这个线程将被终止。
  • BlockingQueue workQueue 工作队列
ThreadPoolExecutor允许提供一个BlockingQueue来保存等待执行的任务。
  • ThreadFactory threadFactory 线程工厂
每当线程池需要创建一个线程时,都是通过线程工厂方法来完成的。默认的线程工厂方法将创建一个新的、非守护的线程,并且不包含特殊的配置信息(默认的线程工厂由Executors.defaultThreadFactory()创建):
public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }
    
 static class DefaultThreadFactory implements ThreadFactory {
        
        ...

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
当然,我们也可以自定义线程工厂类,对我们的线程进行一些自定义的配置,这时候我们只需要继承ThreadFactory接口就可以了:
public interface ThreadFactory {

    /**
     * Constructs a new {@code Thread}.  Implementations may also initialize
     * priority, name, daemon status, {@code ThreadGroup}, etc.
     *
     * @param r a runnable to be executed by new thread instance
     * @return constructed thread, or {@code null} if the request to
     *         create a thread is rejected
     */
    Thread newThread(Runnable r);
}
  • RejectedExecutionHandler handler 饱和政策
当有界队列被填满时,饱和政策开始发挥作用。ThreadPoolExecutor的饱和政策可以通过setRejectedExecutorHandler()进行修改(如何某个任务被提交到一个已被关闭的Executor时,也会用到饱和政策)。JDK默认提供了几种不同的RejectedExecutionHandler实现:
  • AbortPolicy 中止策略(默认的饱和策略):
该策略将抛出未检查的RejectedException。调用者可以捕获这个异常,然后根据需求自己编写自己的处理代码。
/**
 * The default rejected execution handler
 */
private static final RejectedExecutionHandler defaultHandler =
    new AbortPolicy();
    ...
public static class AbortPolicy implements RejectedExecutionHandler {
        
        public AbortPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
  • DiscardPolicy 抛弃策略:
该策略将会悄悄的抛弃该任务。
 public static class DiscardPolicy implements RejectedExecutionHandler {
        
        public DiscardPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            //do nothing
        }
    }
  • DiscardOldestPolicy 抛弃最旧的策略:
该策略将会抛弃下一个将被执行的任务(即工作队列的最前端),然后尝试重新提交这个任务。
 public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        
        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
  • CallerRunsPolicy 调用者运行策略:
该策略实现一直调节机制——它既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量–它将会一个调用了execute()方法的线程中执行该任务。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
      
        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

二、特殊的

Executors.newFixedThreadPool工厂方法将线程池的基本大小和最大大小设置为参数中指定的值,而且创建的线程池不会超时,并且其用一个无界的LinkedBlockingQueue当做工作队列,所以它永远不会调用饱和政策:
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
Executors.newCachedThreadPool工厂方法将线程池的基本大小设置为0,最大大小设置为Integer.MAX_VALUE,超时时间设置为1分钟,并且其用一个SynchronousQueue当做工作队列——SynchronousQueue并不是一个真正的队列,而是一种在线程直接进行移交的机制——要将一个元素放进SynchronousQueue中,必须有一个线程正在等待接受这个元素。如果没有线程正在等待,且线程池的当前大小小于最大值,那么TheardPoolExecutor将创建一个新的线程,否则调用饱和政策:
 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值