线程池

Java常见的创建线程(线程池)有三个:

Executors.newCachedThreadPool();

Executors.newFixedThreadPool(10);

Executors.newSingleThreadExecutor();

查源码,都是new 的一个线程池类 ThreadPoolExecutor,只是参数不同;

ThreadPoolExecutor

参数

ThreadPoolExecutor 的参数有6个:

corePoolSize 、 maximumPoolSize 、 keepAliveTime 、 workQueue

threadFactory 、 handler ;

 

非核心参数:

  • ThreadFactory threadFactory,制造线程的工厂

  • RejectedExecutionHandler handler,线程超过线程池的最大处理量时,抛出拒绝执行异常

核心参数

  • corePoolSize,一直存活的核心线程数,

  • maximumPoolSize,最大线程数,线程池最大容量

  • keepAliveTime,超过corePoolSize数量的空闲线程可存活时间,超过这个时间的线程对象会被销毁

  • workQueue,一个阻塞队列,用例存放任务,等待线程执行

线程池执行流程

假设现在有如下一个线程池

 

线程任务执行流程如下:

  • 先来的任务 T1 ... T10 会直接被 core thread 的 ct1 ... ct10 执行

  • 继续来的任务 T11 ... T20 会被放进 work queue中,因为队列的size=10,就刚好存放 10个任务( core thread 的 ct1 ... ct10 还在执行 T1 ... T10)

  • 继续来的任务 T21 ... T30 ,线程池会创建其他线程对象 other thread(最多10个,因为线程池的最大线程数为20)的 ot1 ... ot10 来执行

  • 如果仍有任务进来 T31... ,此时会报异常,线程池已经不能再执行和保存任务了,后续来的任务都不会执行(RejectedExecutionHandler 处理),因为线程池的最大容量= maximumPoolSize + workQueue = 30

  • 如果有任务执行完成(ct1 ... ct10执行的 T1 ...T10,ot1 ... ot10执行的 T21 ... T31),空闲的线程就会去执行 workQueue中的任务

  • 如果workQueue中的任务也执行完成, 没有其他任务进来,空闲的线程存活 10S(keepAliveTime)后会被销毁(core thread 和 other thread 都有可能被销毁),直到线程池中存活的线程=10个(corePoolSize)

Executors 的三个线程池

newCachedThreadPool()

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

源码可见

  • 核心线程数是 0

  • 最大线程数是 无穷大

  • 空闲线程存活 60S

  • 阻塞队列 SynchronousQueue,看源码可知,size = 0

所以 newCachedThreadPool 是一个初始线程数为0,线程数随着任务增加而增加,没有阻塞队列存放任务,空闲线程存活60S的线程池

newFixedThreadPool()

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

源码可见

  • 核心线程数是传入的参数 nThreads

  • 最大线程数是传入的参数 nThreads

  • 空闲线程存活时间是 0s(corePoolSize=maximumPoolSize,也不会有其他线程进入,线程池的线程数一直都是 nThreads)

  • 阻塞列队 LinkedBlockingQueue,是一个链表,size不限

所以 newFixedThreadPool 是一个 初始线程数和最大线程数都为 nThreads,阻塞队列可存放无限多任务,无需要销毁的空闲线程的线程池

newSingleThreadExecutor()

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

newSingleThreadExecutor 就是只有 一个线程的线程池(特殊的newFixedThreadPool )

posted @ 2022-02-16 23:02  hjy1995  阅读(34)  评论(0编辑  收藏  举报