vlambda博客
学习文章列表

线程池执行以及回收原理(二)

线程回收

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

我们在设置线程池的时候往往会设置keepAliveTime(最大存活时间),我们都知道如果超过这个存活时间,线程池会回收额外的线程达到核心线程数,

1、回收的原理是什么?

2、核心线程与非核心线程有什么区别吗?

3、非核心线程可以核心线程吗?

在线程池执行以及回收原理(一)主要讲述了线程在执行过程中的创建以及如何获取task任务,下面就是getTask()的任务


  
    
    
  
  1. private Runnable getTask() {

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

  3. for (;;) {

  4. int c = ctl.get();

  5. int rs = runStateOf(c);

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

  7. decrementWorkerCount();

  8. return null;

  9. }

  10. int wc = workerCountOf(c);

  11. // 步骤1

  12. boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

  13. // 步骤2

  14. if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) {

  15. // 步骤2.1

  16. if (compareAndDecrementWorkerCount(c))

  17. return null;

  18. continue;

  19. }

  20. try {

  21. // 步骤3

  22. Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();

  23. if (r != null)

  24. return r;

  25. timedOut = true;

  26. } catch (InterruptedException retry) {

  27. timedOut = false;

  28. }

  29. }

  30. }

在步骤3中: workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) keepAliveTime在这里使用,表示workQueue等待keepAliveTime的时长,若果没有获取到或者超时返回null值。

workQueue具体含义什么呢?从上一篇文章可以知道线程池执行以及回收原理(一),这是一个阻塞队列,当核心线程数 =< 当前线程数 < 最大线程数时,我们将任务封装放进一个阻塞队列,这就是那个阻塞队列;

整体我们就可以知道,

1、如果队列中没有任务的,步骤3获取的r参数为空,timeout就会设置成true

2、进行步骤1的判断,假设这个线程执行的时候wc > corePoolSize成立,则timed为true,步骤2中timed && timedOutweitrue,wc >1也为true,

3、进行步骤2.1的操作,使用cas进行ctl减1的操作,返回null值,此时线程等待系统的回收。

所有的线程都进行如此的操作直到wc > corePoolSize不再成立,ctl这个工作线程的数目等于corePoolSize,此时步骤1获取的timed为false,此时步骤2的判断不再成立,执行步骤3的操作,但是注意此时timed为false,执行三元运算符中的workQueue.take(),此操作是阻塞的,直到workQueue中可以获取到值才能继续运行。这也就是整体的线程池的回收直至存活数目等于核心线程数目

有个关键参数allowCoreThreadTimeOut,这个参数默认是false,如果设置成true,所有的线程都会回收。

这样我们就可以回答上面的问题2与问题3了。

核心线程与非核心线程有什么区别?非核心线程可以核心线程吗?他们两个没有什么区别,能否成为核心线程完全是随机的,主要就是看谁先能提前进入阻塞当中,谁就会成为最终留下来的核心线程

下图是线程池的原理示意图

 

https://www.cnblogs.com/semi-sub/p/13908099.html

回复  8888可以领取面试资料,感谢各位小伙伴的关注