线程池原理和机制简述

一:结构
线程池一般有core 线程数,最大线程数和缓存队列(阻塞队列)组成。
二:线程复用原理
线程池里面的线程(真正线程,start 方法启动的)运行业务线程对象(Thread 或者Runable 对象,但不是真正的线程)的run (非start方法)方法。

三:线程池逻辑

线程池原理和机制简述_第1张图片

四:常用线程池

1:newFixedThreadPool


public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue());
}
其中最大线程和核心线程一致,用的是LinkedBlockingQueue,无限容量。

2:newSingleThreadExecutor


public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue()));
}
其中最大线程和核心线程一致,用的是LinkedBlockingQueue,无限容量。

3:newCachedThreadPool


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

全部外包,没活最多待 60 秒的外包团队。

可以看到,CachedThreadPool 没有核心线程,非核心线程数无上限,也就是全部使用外包,但是每个外包空闲的时间只有 60 秒,超过后就会被回收。

CachedThreadPool 使用的队列是 SynchronousQueue,这个队列的作用就是传递任务,并不会保存。

因此当提交任务的速度大于处理任务的速度时,每次提交一个任务,就会创建一个线程。极端情况下会创建过多的线程,耗尽 CPU 和内存资源。

它的执行流程如下:

  1. 没有核心线程,直接向 SynchronousQueue 中提交任务
  2. 如果有空闲线程,就去取出任务执行;如果没有空闲线程,就新建一个
  3. 执行完任务的线程有 60 秒生存时间,如果在这个时间内可以接到新任务,就可以继续活下去,否则就拜拜

由于空闲 60 秒的线程会被终止,长时间保持空闲的 CachedThreadPool 不会占用任何资源。

CachedThreadPool 用于并发执行大量短期的小任务,或者是负载较轻的服务器



4:newScheduledThreadPool

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());
}
private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;

核心线程和最大线程都有,采用DelayedWorkQueue 队列,最像第三章说的流程的线程池。

你可能感兴趣的:(架构)