好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

java 线程池keepAliveTime的含义说明

之前对线程池中属性:keepAliveTime比较模糊,而且看过之后过一段时间就会忘掉,于是就在此记录一下。

keepAliveTime的jdk中的解释为:

当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

说的让人感觉比较模糊,总结一下大概意思为:比如说线程池中最大的线程数为50,而其中只有40个线程任务在跑,相当于有10个空闲线程,这10个空闲线程不能让他一直在开着,因为线程的存在也会特别好资源的,所有就需要设置一个这个空闲线程的存活时间,这么解释应该就很清楚了。

这样以后忘记了就过来看看就OK了。

补充:线程池的状态及KeepAliveTime参数

五个状态

?

1

2

3

4

5

6

// runState is stored in the high-order bits

private static final int RUNNING = - 1 << COUNT_BITS;

private static final int SHUTDOWN = 0 << COUNT_BITS;

private static final int STOP  = 1 << COUNT_BITS;

private static final int TIDYING = 2 << COUNT_BITS;

private static final int TERMINATED = 3 << COUNT_BITS;

循环getTask方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

/**

   * Performs blocking or timed wait for a task, depending on

   * current configuration settings, or returns null if this worker

   * must exit because of any of:

   * 1. There are more than maximumPoolSize workers (due to

   * a call to setMaximumPoolSize).

   * 2. The pool is stopped.

   * 3. The pool is shutdown and the queue is empty.

   * 4. This worker timed out waiting for a task, and timed-out

   * workers are subject to termination (that is,

   * {@code allowCoreThreadTimeOut || workerCount > corePoolSize})

   * both before and after the timed wait.

   *

   * @return task, or null if the worker must exit, in which case

   *   workerCount is decremented

   */

  private Runnable getTask() {

   boolean timedOut = false ; // Did the last poll() time out?

   retry:

   for (;;) {

    int c = ctl.get();

    int rs = runStateOf(c);

    // Check if queue empty only if necessary.

    if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {

     decrementWorkerCount();

     return null ;

    }

    boolean timed;  // Are workers subject to culling?

    for (;;) {

     int wc = workerCountOf(c);

     timed = allowCoreThreadTimeOut || wc > corePoolSize;

     //默认allowCoreThreadTimeOut为false,除非程序指定

     //(1)当没有超过核心线程时,默认allowCoreThreadTimeOut为false时

     //timed值为false,始终break掉,不会销毁线程

     //(2)当超过核心线程数,默认allowCoreThreadTimeOut为false时

     //timed值为true,如果超过最大值,则销毁;如果timeout过,则销毁

     // 如果allowCoreThreadTimeOut为true,则timed始终为true

     if (wc <= maximumPoolSize && ! (timedOut && timed))

      break ;

     if (compareAndDecrementWorkerCount(c))

      return null ;

     c = ctl.get(); // Re-read ctl

     if (runStateOf(c) != rs)

      continue retry;

     // else CAS failed due to workerCount change; retry inner loop

    }

    try {

     Runnable r = timed ?

      workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :

      workQueue.take();

     if (r != null )

      return r;

     timedOut = true ;

    } catch (InterruptedException retry) {

     timedOut = false ;

    }

   }

  }

线程池状态大于SHUTDOWN值的两种情况

1、调用shutdown方法

当线程池调用了shutdown方法,线程池的状态会首先被设置为SHUTDOWN,然后遍历线程池中所有线程,调用一次interrupt方法,如果在休眠中的线程将会激活,激活后的线程以及调用shutdown方法本身的线程都会尝试去调用tryTerminate方法,该方法将判定如果线程池中所有记录的线程数为0,则将线程状态改为TERMINATED,这个值为3,将大于SHUTDOWN状态值。

2、调用shutdownNow方法

当线程调用了shutdownNow方法后,首先将线程的状态修改为STOP,这个状态是大于SHUTDOWN值的,接下来它也会通过中断激活线程,只是它来的更暴力一些,连加锁和一些基本判断都没有,直接中断;在调用tryTerminate之前会先清空阻塞队列中所有的元素,这些元素被组装为一个List列表作为shutdownNow方法的返回值。换句话说,没有执行的任务在shutdownNow执行后的返回值中可以得到。在程序某些必要的情况下,可以通过线程池的isTerminating,isTerminated,isStopped,isShutdown来对线程做一些状态判定。

KeepAliveTime参数

?

1

workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)

当阻塞队列中没有任务时,等待时间达到keepAliveTime毫秒值时就会被自动唤醒,而不会永远地沉睡下去。

keepAliveTime,如果是通过newCachedThreadPool的话,默认是1分钟超时,如果遇到前面所提到的瞬间冲击,那么线程池数量将瞬间快速膨胀,而且这些瞬间膨胀的线程的生命周期最少在1分钟以上。

如果设置了该参数,那么当timeout的时候,就return null,就会跳出循环,回收线程。

?

1

2

3

4

if (wc <= maximumPoolSize && ! (timedOut && timed))

      break ;

     if (compareAndDecrementWorkerCount(c))

      return null ;

allowCoreThreadTimeout : 默认情况下核心线程不会退出,可通过将该参数设置为true,让核心线程也退出。

默认的Executors工厂,只有newCachedThreadPool,timeout为60秒,出现timeout情况下,而且线程数超过了核心线程数,会销毁销毁线程。保持在corePoolSize数(如果是cached的,corePoolSize为0)。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

/**

  * Timeout in nanoseconds for idle threads waiting for work.

  * Threads use this timeout when there are more than corePoolSize

  * present or if allowCoreThreadTimeOut. Otherwise they wait

  * forever for new work.

  */

private volatile long keepAliveTime;

/**

  * If false (default), core threads stay alive even when idle.

  * If true, core threads use keepAliveTime to time out waiting

  * for work.

  */

private volatile boolean allowCoreThreadTimeOut;

线程池最小是corePoolSize,最大是maximumPoolSize,除非设置了allowCoreThreadTimeOut和超时时间,这种情况线程数可能减少到0,最大可能是Integer.MAX_VALUE。

Core pool size is the minimum number of workers to keep alive(and not allow to time out etc) unless allowCoreThreadTimeOut is set, in which case the minimum is zero.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

/**

   * Creates a thread pool that creates new threads as needed, but

   * will reuse previously constructed threads when they are

   * available. These pools will typically improve the performance

   * of programs that execute many short-lived asynchronous tasks.

   * Calls to <tt>execute</tt> will reuse previously constructed

   * threads if available. If no existing thread is available, a new

   * thread will be created and added to the pool. Threads that have

   * not been used for sixty seconds are terminated and removed from

   * the cache. Thus, a pool that remains idle for long enough will

   * not consume any resources. Note that pools with similar

   * properties but different details (for example, timeout parameters)

   * may be created using {@link ThreadPoolExecutor} constructors.

   *

   * @return the newly created thread pool

   */

  public static ExecutorService newCachedThreadPool() {

   return new ThreadPoolExecutor( 0 , Integer.MAX_VALUE,

           60L, TimeUnit.SECONDS,

           new SynchronousQueue<Runnable>());

  }

  /**

   * Creates a thread pool that creates new threads as needed, but

   * will reuse previously constructed threads when they are

   * available, and uses the provided

   * ThreadFactory to create new threads when needed.

   * @param threadFactory the factory to use when creating new threads

   * @return the newly created thread pool

   * @throws NullPointerException if threadFactory is null

   */

  public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {

   return new ThreadPoolExecutor( 0 , Integer.MAX_VALUE,

           60L, TimeUnit.SECONDS,

           new SynchronousQueue<Runnable>(),

           threadFactory);

  }

超时timeout设置为0的话,表示不等待

?

1

2

3

public E poll( long timeout, TimeUnit unit) throws InterruptedException {

   return pollFirst(timeout, unit);

  }

具体如下

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public E pollFirst( long timeout, TimeUnit unit)

   throws InterruptedException {

   long nanos = unit.toNanos(timeout);

   final ReentrantLock lock = this .lock;

   lock.lockInterruptibly();

   try {

    E x;

    while ( (x = unlinkFirst()) == null ) {

     if (nanos <= 0 )

      return null ;

     nanos = notEmpty.awaitNanos(nanos);

    }

    return x;

   } finally {

    lock.unlock();

   }

  }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://blog.csdn.net/jianjun200607/article/details/44303561

查看更多关于java 线程池keepAliveTime的含义说明的详细内容...

  阅读:21次