java 线程池参数

博客介绍了Executors提供的四种线程池,包括缓存、定长、计划和单线程线程池。指出它们都是ThreadPoolExecutor对象,只是参数不同。详细解析了ThreadPoolExecutor的7个核心参数,如线程池基本大小、最大线程数等,还说明了线程池状态,如RUNNING、SHUTDOWN等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Executors提供四种线程池:
newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool : 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool : 计划线程池,支持定时及周期性任务执行。
newSingleThreadExecutor :单线程线程池,用唯一的线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

从源码可以看出这四种线程池都是ThreadPoolExecutor的对象,只是传入的参数不同。

以 newFixedThreadPool为例:

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

ThreadPoolExecutor有许多构造方法,最终会调用参数最多的构造方法:

 

public ThreadPoolExecutor(    int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

                //……
}

这7个参是面试的核心考题:

在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程; keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0; unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

 

1、corePoolSize:线程池的基本大小。

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

poolSize:线程池中当前线程的数量。

那么poolSize、corePoolSize、maximumPoolSize三者的关系是如何的呢?
当新提交一个任务时:
(1)如果poolSize<corePoolSize,新增加一个线程处理新的任务。
(2)如果poolSize=corePoolSize,新任务会被放入阻塞队列等待。
(3)如果阻塞队列的容量达到上限,且这时poolSize<maximumPoolSize,新增线程来处理任务。
(4)如果阻塞队列满了,且poolSize=maximumPoolSize,那么线程池已经达到极限,会根据饱和策略RejectedExecutionHandler拒绝新的任务。

所以通过上面的描述可知corePoolSize<=maximumPoolSize,poolSize<=maximumPoolSize;而poolSize和corePoolSize无法比较,poolSize是有可能比corePoolSize大的。

那么corePoolSize、maximumPoolSize在上面四种线程池中如何设定的?
通过几个newXXX函数的源码就可以知道,源码如下:
(1)

//定长线程池的corePoolSize、maximumPoolSize相同。都是设定值
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

//缓存线程池corePoolSize为0,maximumPoolSize则是int最大值。
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

//单线程线程池corePoolSize和maximumPoolSize都是1。
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

//计划线程池用的是ThreadPoolExecutor的一个子类ScheduledThreadPoolExecutor,可以看到corePoolSize是定义的,而maximumPoolSize则是int最大值。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}



注意这里的corePoolSize、maximumPoolSize不是最终的,因为可以通过setCorePoolSize和setMaximumPoolSize()改变。

上面提到阻塞队列的饱和,那么这个饱和值是多少呢?


通过上面的代码可以看到
(1)定长线程池和单线程线程都使用LinkedBlockingQueue,而LinkedBlockingQueue默认的大小是int的最大值,也可以指定大小如下:

public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
}

 

(2)计划线程池使用的是DelayedWordQueue,它默认大小是16,但是可以动态增长,最大值则是int的最大值,如下:

private static final int INITIAL_CAPACITY = 16;
private RunnableScheduledFuture<?>[] queue =
    new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
private void grow() {
    int oldCapacity = queue.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
    if (newCapacity < 0) // overflow
        newCapacity = Integer.MAX_VALUE;
    queue = Arrays.copyOf(queue, newCapacity);
}

(3)缓存线程池使用的则是SynchronousQueue,这个比较特殊没有所谓的饱和值,而且前面也看到了缓存线程池的corePoolSize默认是0。所以它新建一个线程与SynchronousQueue的机制有关,这里不展开说了,有兴趣的可以研究一下这个类。

https://blog.csdn.net/sky_100/article/details/75174250

https://blog.csdn.net/weixin_41509424/article/details/84063561

 

3、keepAliveTime:当线程数大于核心时,这是多余的空闲线程在终止前等待新任务的最长时间。
4、unit:TimeUnit枚举类型的值,代表keepAliveTime时间单位,可以取下列值:
TimeUnit.DAYS; //天
  TimeUnit.HOURS; //小时
  TimeUnit.MINUTES; //分钟
  TimeUnit.SECONDS; //秒
  TimeUnit.MILLISECONDS; //毫秒
  TimeUnit.MICROSECONDS; //微妙
  TimeUnit.NANOSECONDS; //纳秒
5、workQueue:阻塞队列,用来存储等待执行的任务,决定了线程池的排队策略,有以下取值:
  ArrayBlockingQueue;
  LinkedBlockingQueue;
  SynchronousQueue;
6、threadFactory:线程工厂,是用来创建线程的。默认new Executors.DefaultThreadFactory();
7、handler:线程拒绝策略。当创建的线程超出maximumPoolSize,且缓冲队列已满时,新任务会拒绝,有以下取值:
  ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,默认。 
  ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
  ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
  ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

 

 

 

线程池状态:

资源有限情况,可以避免资源被耗尽。一个AtomicInteger的ctl用于包装线程状态runState和任务线程数workerCount;低29位保存任务线程数,高两位用于存储线程池状态,线程池状态已用有五种RUNNING,SHUTDOWN ,STOP,TIDYING ,TERMINATED。 
RUNNING:接受新的任务,处理队列任务; 
SHUTDOWN:不在接受新的任务,处理队列任务; 
STOP:不在接受新任务,不处理队列任务,中断正在执行的任务线程; 
TIDYING:所有的任务已经结束,任务线程为0,线程转换到TIDYING; 
TERMINATED:线程池已结束,即terminated()方法执行完。 

 

https://donald-draper.iteye.com/blog/2366934

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值