Java线程池参数

通过构造函数分析线程池

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

一共有7个参数,详细解释如下

  1. coresize
    核心线程池线程数目,也可以理解为线程池基本大小
  2. maximumpoolsize
    线程池的最大大小
  3. keepAliveTime
    存活时间,如果一个线程不在基本线程池中,那么这个线程在经过AliveTime时间之后会被回收线程资源
  4. TimeUtil
    时间的单位
  5. BlockingQueue
    阻塞队列,存储runnable任务
  6. ThreadFactory
    线程创建工厂
  7. RejectedExecutionHandler
    拒绝继续执行runnnable的处理器

当线程池第一次提交Runnable时

excutor.excute(new  Runnable() {
      public void run() {}
 })

由于刚开始是没有线程的,因此我们需要创建线程,创建线程时我们需要将当前线程的数量与coreSize相比较,如果小于则直接创建线程,如果超出了这个coreSize的大小,则把任务填充到BlockingQueue阻塞队列中,当有空闲线程时再从阻塞队列中读取,这属于生产中-消费者模型,当阻塞队列已满时,将当前任务数与
maximumPoolSize比较,如果小于溢出的任务将继续创建线程,如果大于则触发RejectedExecutionHandler。整个过程中,线程的创建由ThreadFactory来完成。那么keepAliveTime又是如何处理的呢?我们注意到,在阻塞队列满之后,我们仍然是通过创建线程的方式来处理runnable的,那么,coresize的线程与maxSize的线程的区别又在哪呢?实际上,只有对于非基本线程(coreSize以内的),在keepAliveTime时间后会被回收线程资源,而基本线程数目则是再被懒加载之后就再也不会变动了。

Executors静态工厂方法创建线程池

jdk提供了以下几个方法创建几种典型的线程池,我们可以分别看看他们的构造函数转而真正理解他们的原理

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

用于创建固定长度的线程池

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

用于创建单个线程的线程池,可能会有人认为创建单个线程的线程池是没有意义的,但是实际上,由于阻塞队列的存在,因此这种模式可以提交多个runnable,并且保证他们的顺序调用。而且有时不正确的异常处理会导致线程被终结,而线程池可以确保总是存在一个线程用来执行任务。

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

基于缓存的线程池,由参数我们可知,coresize为0,而maxSize为最大值,因此此类线程池对于提交的任务,总是会创建线程,而线程在空闲时会被回收

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

定时任务执行的线程池,原理是使用了DelayedWorkQueue

拒绝执行策略

  1. 拒绝执行并抛出异常 (默认的执行策略)
  2. 直接使用当前执行excute方法线程执行这个任务
  3. 直接丢弃当前队列中最老的任务
  4. 直接抛弃而不做处理

其他策略

  1. 写入日志用于以后再处理
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值