admin管理员组

文章数量:1530518

2023年12月13日发(作者:)

jetty的线程池-QueuedThreadPool

一直对线程池有些疑问:

1.线程池怎么保证线程一直存在?

2.线程池怎么控制最大空闲时间?

3.线程池怎么回收线程?

。。。。

带着这些问题,看了一边jetty的线程池。

jetty有三个线程池,分别是ExecutorThreadPool,OldQueuedThreadPool,QueuedThreadPool

它们都实现了Pool接口,并继承ctLifeCycle

这里我们只关注QueuedThreadPool。

看名字就知道,它是跟队列相关的,没错。

QueuedThreadPool的存放jbos的集合(BlockingQueue ),

和存放线程的集合都是用队列实现的(ConcurrentLinkedQueue)

看看QueuedThreadPool前面定义的private属性:

Java代码

1. public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, Executor {

2. //已经启动的线程数

3. private final AtomicInteger _threadsStarted = new AtomicInteger();

4. //空闲线程数

5. private final AtomicInteger _threadsIdle

= new AtomicInteger();

6. //上一次执行销毁线程的时间。这个就是用来控制最大空闲时间的

7. private final AtomicLong _lastShrink

= new AtomicLong();

8. //存放线程的集合

9. private final ConcurrentLinkedQueue _threads

= new ConcurrentLinkedQueue();

10.//一个锁

11. private final Object _joinLock

= new Object();

12.//存放任务的集合

13. private BlockingQueue _jobs;

14.//以上这些都是线程安全的

15.

16.//下面这些都是参数,不会变的,所以无需线程安全控制

17. private String _name; 18. private int _maxIdleTimeMs

= 60000;

19. private int _maxThreads

= 254;

20. private int _minThreads

= 8;

21. private int _maxQueued

= -1;

22. private int _priority

= _PRIORITY;

23. private boolean _daemon

= false;

24. private int _maxStopTime

= 100;

jetty里面的核心类都实现了lifecycle接口,所以该线程池初始化的时候,是调用的doStart()方法。

Java代码

1. protected void doStart() throws Exception {

2. t();

3. _(0);

4.

5. if (_jobs == null) {

6. _jobs = _maxQueued > 0 ? new ArrayBlockingQueue(_maxQueued) : new BlockingArrayQueue(

7.

_minThreads,

8.

_minThreads);

9. }

10.

11. int threads = _();

12. // 启动一定数量的线程

13. while (isRunning() && threads < _minThreads) {

14. //启动线程

15. startThread(threads);

16. threads = _();

17. }

18. } 首先初始化了父类,接着设置 已经启动的线程数=0,设置存放jbos的集合。

然后就开始启动线程了。直到已经启动的线程数=最小线程数。

至此,完成初始化。

再来看看startThread方法:

Java代码

1. ...............

2. Thread thread = newThread(_runnable);

3. mon(_daemon);

4. ority(_priority);

5. e(_name + "-" + ());

6. _(thread);

7. ();

8. ..............

仅仅是启动了一个_runnable对象。其他的都没啥好看的。

赶紧看看这个_runnable是咋样的。

_runnable是一个runnable的匿名类,它的run方法里是一个while循环

Java代码

1. while (isRunning()) {

2. jobs

3. 2.阻塞或者回收线程

1.循环的从任务队列里面取任务,直到任务队列为空

Java代码

1. // 首先把jobs里面的任务都执行掉

2. / 首先把jobs里面的任务都执行掉

3. while (job != null && isRunning()) {

4. ();

5. // ()不阻塞,如果木有,直接返回null

6. job = _();

7. }

2.接着,阻塞线程,回收线程 Java代码

1. // 没有可执行的任务,空闲线程数量+1

2. _entAndGet();

3. // 木有任务的情况下,使劲循环

4. while (isRunning() && job == null) {

5. // ()会阻塞,直到有一个job返回,这样就维持了线程一直存在着

6. // 最大空闲时间<=0,则不回收线程,直接阻塞线程,等待任务

7. if (_maxIdleTimeMs <= 0) job = _();

8. else {

9. // maybe we should shrink?

10. // 已经启动的线程数

11. final int size = _();

12. // 已经启动的线程数>_minThreads,判断是否需要回收

13. if (size > _minThreads) {

14. // 上一次回收线程的时间

15. long last = _();

16. // now

17. long now = tTimeMillis();

18. // 两次回收之间的时间间隔>最大空闲时间

19. if (last == 0 || (now - last) > _maxIdleTimeMs) {

20. // 回收掉

21. shrink = _eAndSet(last, now)

22. && _eAndSet(size,

23. size - 1);

24. if (shrink) return;

25. }

26. }

27. // 阻塞最大空闲时间,然后返回。

28. // 这次返回以后,如果让然没有任务可执行,并且启动的线程数>_minThreads,则会回收掉

29. job = _(_maxIdleTimeMs, ECONDS);

30. }

31. }

本文标签: 线程任务时间回收空闲