线程池随笔

01 缘由

  线程池是多线程的一种处理方式. 可以统一管理线程, 某些情况下可复用线程, 减少内存开支, 提供更多功能(定时执行, 并发控制等).

02 了解

  常见有四种线程池, 由 Executors 创建.

        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();    //可缓存线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);    //固定大小线程池
        ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);  //周期任务线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();  //单线程化线程池

   但是点开实现, 每个线程池的创建方法都是类似的.

   

    //newCachedThreadPool()
  public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0,
            Integer.MAX_VALUE,
60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }       
    //newFixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }     //newScheduledThreadPool() supe:ThreadPoolExecuotr public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }   //newSingleThreadExecutor() public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }

  追踪源头 ThreadPoolExecutor 的构造方法:

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

  

序号 名称 类型 含义
1 corePoolSize int 核心线程池大小
2 maximumPoolSize int 最大线程池大小
3 keepAliveTime long 线程最大空闲时间
4 unit TimeUnit 时间单位
5 workQueue BlockingQueue<Runnable> 线程等待队列
6 threadFactory ThreadFactory 线程创建工厂
7 handler RejectedExecutionHandler 拒绝策略
      
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  1.当线程池小于corePoolSize时, 新提交任务将创建一个新线程执行任务, 即使此时线程池中存在空闲线程. 需要注意的是在初创建线程池时线程不会立即启动, 直到有任务提交才开始启动线程并逐渐时线程数目达到corePoolSize. 若想一开始就创建所有核心线程需调用prestartAllCoreThreads方法.

  2.当线程池达到corePoolSize时, 新提交任务将被放入workQueue中, 等待线程池中任务调度执行.

  3.当workQueue已满, 且maximumPoolSize>corePoolSize时, 新提交任务会创建新线程执行任务.

  4.当提交任务数超过maximumPoolSize时, 新提交任务由RejectedExecutionHandler处理. 需要注意的是在初创建线程池时线程不会立即启动, 直到有任务提交才开始启动线程并逐渐时线程数目达到corePoolSize, 若想一开始就创建所有核心线程需调用prestartAllCoreThreads方法.

  5.当线程池中超过corePoolSize线程, 空闲时间达到keepAliveTime时, 关闭空闲线程.

  6.当设置allowCoreThreadTimeOut(true)时, 线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭.

  7.当阻塞队列已满且线程数达到最大值时会采取对应的拒绝策略RejectedExecutionHandler, java默认提供了4种拒绝策略的实现方式: 中止, 抛弃, 抛弃最旧的, 调用者运行. 

  
 
  了解完构造方法之后, 能够更加清晰的看到每种线程池为什么会这样执行. 我们可以做的就是根据需要手动的创建线程池.
  阻塞队列, 线程工厂, 拒绝策略有需求的可以自己指定. 
 
  补充:

    Alibaba命名规范的解释:

    【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明: Executors 返回的线程池对象的弊端如下:

      1) FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。

      2) CachedThreadPool 和 ScheduledThreadPool : 允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。

猜你喜欢

转载自www.cnblogs.com/fuershi/p/10769146.html