• java中四种线程池及poolSize、corePoolSize、maximumPoolSize


    Executors提供四种线程池:
    • newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。
    • newFixedThreadPool : 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    • newScheduledThreadPool : 计划线程池,支持定时及周期性任务执行。
    • newSingleThreadExecutor :单线程线程池,用唯一的线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
     
    ThreadPoolExecutor有几个重要的成员变量:keepAliveTime、allowCoreThreadTimeOut、poolSize、corePoolSize、maximumPoolSize。下面分别介绍一下:
     
    corePoolSize:线程池的基本大小。下面会解释什么是基本大小。
     
    maximumPoolSize:线程池中允许的最大线程数。
    注意还有一个largestPoolSize,记录了曾经出现的最大线程个数。因为setMaximumPoolSize()可以改变最大线程数。
     
    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)
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    定长线程池的corePoolSize、maximumPoolSize相同。都是设定值。
     
    (2)
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    缓存线程池corePoolSize为0,maximumPoolSize则是int最大值。
     
    (3)
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    单线程线程池corePoolSize和maximumPoolSize都是1。
     
    (4)
    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());
    }
    计划线程池用的是ThreadPoolExecutor的一个子类,可以看到corePoolSize是定义的,而maximumPoolSize则是int最大值。
    注意这里的corePoolSize、maximumPoolSize不是最终的,因为可以通过setCorePoolSize和setMaximumPoolSize()改变。
     
    上面提到阻塞队列的饱和,那么这个饱和值是多少呢?
    通过上面的代码可以看到
    (1)定长线程池和单线程线程都使用LinkedBlockingQueue,而LinkedBlockingQueue默认的大小是int的最大值,如下:
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
     
    (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的机制有关,这里不展开说了,有兴趣的可以研究一下这个类。
     
     
    allowCoreThreadTimeOut:
    是否允许核心线程超时退出。
    如果该值为false,且poolSize<=corePoolSize,线程池都会保证这些核心线程处于存活状态,不会超时退出。
    如果为true,则不论poolSize的大小,都允许超时退出。
    如果poolSize>corePoolSize,则该参数不论true还是false,都允许超时退出。
    相关判断如下:
    (poolSize > corePoolSize || allowCoreThreadTimeOut)
     

    keepAliveTime:

    如果一个线程处在空闲状态的时间超过了该属性值,就会因为超时而退出。是否允许超时退出则取决于上面的逻辑。
  • 相关阅读:
    解决ajax 发送post 请求时csrf_token 问题
    pip 常用命令
    mac 查看端口的使用情况
    使用from __future__ import unicode_literals
    git 使用
    django rest_framework
    Apache JMeter 接口压力测试
    HTTP 协议
    自定义异步非阻塞web框架
    WebSocket
  • 原文地址:https://www.cnblogs.com/cxy2020/p/13523550.html
Copyright © 2020-2023  润新知