深入理解java线程池ThreadPoolExecutor

我们在工程项目中,有时候既想拥有不错的并发体验,又想不要在应用中创建太多的线程(线程的创建还是有一定的开销的),这时就得用到jdk中的ThreadPoolExecutor类,相信java程序员对这个很面熟,但对于初学者来说,这里还是有一些细节需要注意一下。

首先们来看下ThreadPoolExecutor的构造函数,一共有4个重载的构造函数:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);
}


public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), handler);
}

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

参数 threadFactory(可缺省)是用来指定线程创建的工厂类

参数 handler(可缺省)以下两种情况会触发:

  1. 当线程池已满负荷运行时(即正在执行的线程已经达到maximumPoolSize时),且workQueue也满的时候;
  2. 或者当调用者执行ThreadPoolExecutor#shutdown()来关闭线程池时

此时再通过ThreadPoolExecutor#execute()添加新的task时,就会触发,如果没有指定,execute()会抛出RejectedExecutionException异常(详见AbortPolicy类)

参数 corePoolSize 和 maximumPoolSize 用来控制线程池中常驻的线程数和最大池程数。

参数 keepAliveTime 和 unit(keepAliveTime的单位)用来控制当线程数超过corePoolSize时,超出corePoolSize且空闲的线程如果在keepAliveTime之内还未有新的task执行,则就会被释放。当然我们也可以通过ThreadPoolExecutor#allowCoreThreadTimeOut()来将keepAliveTime应用到corePoolSize之内的线程。

参数 workQueue 用来当线程已达到corePoolSize时,新添加的task会存入workQueue等待执行。

这里需要注意的是:

  1. 当线程数小于corePoolSize时,添加新的task时,就算有空闲的线程,ThreadPoolExecutor也会创建新的线程来执行
  2. 当正在运行的线程已达到corePoolSize时,添加新的task,就算当前线程数未达到maximumPoolSize,也会直接扔到workQueue等待执行。也就是说,当workQueue是可以无限扩展的队列时,maximumPoolSize,keepAliveTime和unit三个参数就会变得毫无意义

demo:

//创建一个常驻线程数为3,最大线程数为5,超出常驻线程数的空闲线程最大等待时间为1分钟,且最大等待的task数为1024的线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1, TimeUnit.MINUTES, 
                                                               new ArrayBlockingQueue<Runnable>(1024));

threadPoolExecutor.execute(new Runnable(){
   @Override
   public void run() {
      System.out.println("test");
   }
});

加入我们:http://www.duoceshi.com/team.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值