ThreadPoolExecutor详解

一、线程池参数介绍

 /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:
* {@code corePoolSize < 0}
* {@code keepAliveTime < 0}
* {@code maximumPoolSize <= 0}
* {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code threadFactory} or {@code handler} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue 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; }
  • corePoolSize: 池内线程初始值与最小值,就算是空闲状态,也会保持该数量线程。

CPU密集型任务,IO密集型任务和混合型任务:
任务性质不同的任务可以用不同规模的线程池分开处理。CPU密集型任务配置尽可能小的线程,如配置Ncpu+1个线程的线程池。IO密集型任务则由于线程并不是一直在执行任务,则配置尽可能多的线程,如2Ncpu。混合型的任务,如果可以拆分,则将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率,如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。如果是IO密集型任务,参考值可以设置为2NCPU

  • maximumPoolSize: 线程最大值,线程的增长始终不会超过该值。
  • keepAliveTime: 当池内线程数高于corePoolSize时,经过多少时间多余的空闲线程才会被回收。回收前处于wait状态
  • unit: 时间单位,可以使用TimeUnit的实例,如TimeUnit.MILLISECONDS
  • workQueue: 待入任务(Runnable)的等待场所,该参数主要影响调度策略,如公平与否,是否产生饿死(starving)
  • threadFactory: 线程工厂类,有默认实现,如果有自定义的需要则需要自己实现ThreadFactory接口并作为参数传入。
  • RejectedExecutionHandler: 线程池的拒绝策略
    • AbortPolicy:对拒绝任务抛弃处理,并且抛出异常。【默认线程池拒绝策略】
    • DiscardPolicy:对拒绝任务直接无声抛弃,没有异常信息。
    • DiscardOldestPolicy:对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。
    • CallerRunsPolicy:这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。

二、线程池执行流程

ThreadPoolExecutor详解_第1张图片
1.png
  1. 如果线程池中的线程数量少于corePoolSize,就创建新的线程来执行新添加的任务
  2. 如果线程池中的线程数量大于等于corePoolSize,但队列workQueue未满,则将新添加的任务放到workQueue中
  3. 如果线程池中的线程数量大于等于corePoolSize,且队列workQueue已满,但线程池中的线程数量小于maximumPoolSize,则会创建新的线程来处理被添加的任务
  4. 如果线程池中的线程数量等于了maximumPoolSize,就用RejectedExecutionHandler来执行拒绝策略

三、线程池状态

  • RUNNING:接受新的任务,处理队列任务;
  • SHUTDOWN:不在接受新的任务,处理队列任务;
  • STOP:不在接受新任务,不处理队列任务,中断正在执行的任务线程;
  • TIDYING:所有的任务已经结束,任务线程为0,线程转换到TIDYING;
  • TERMINATED:线程池已将结束,即terminated()方法执行完。

四、线程的生命周期

  1. 新建(new Thread)
    当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
    例如:Thread t1=new Thread();

  2. 就绪(runnable)
    线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

  3. 运行(running)
    线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

  4. 死亡(dead)
    当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
    自然终止:正常运行run()方法后终止
    异常终止:调用stop()方法让一个线程终止运行

  5. 堵塞(blocked)
    由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
    正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
    正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
    被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

你可能感兴趣的:(ThreadPoolExecutor详解)