亲 , ThreadPoolExecutor : KeepAliveTime了解一下~
Posted JAVA翻译官
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了亲 , ThreadPoolExecutor : KeepAliveTime了解一下~相关的知识,希望对你有一定的参考价值。
先来几个问题:
如果你来设计这个超时,会怎么设计?
> corePoolSize的线程要不要去执行queue里的task ?
来看看ThreadPoolExecutor 怎么做的?
现在有一个ThreadPoolExecutor,有以下属性:
1corePoolSize : 1 //核心线程数 1
2maximumPoolSize : 2 // 最大线程数 2
3queueSize : 1 // 队列容量 1
4keepAliveTime : 5s //存活时间 ,5s
5allowCorePoolTimeOut: false //核心线程不超时
有三个task ,每个task执行不同的时间:
1T1 : 20s // task 1 执行 20s
2T2 : 10s // task 2 执行 10s
3T3 : 5s // task 3 执行 5s
有以下这个,指定休眠时间的任务:
1 @Override
2 public void run() {
3 String name = new StringBuilder(Thread.currentThread().getName()).append("-").append(Thread.currentThread().getId()).toString();
4 System.out.println(name + " : start , time:"+time);
5 try {
6 TimeUnit.SECONDS.sleep(time);
7 } catch (InterruptedException e) {}
8 System.out.println(name + " : end , time:"+time);
9 }
得到如下结果:
1pool-1-thread-1-11 : start , time:20
2pool-1-thread-2-12 : start , time:5
3pool-1-thread-2-12 : end , time:5
4pool-1-thread-2-12 : start , time:10
5pool-1-thread-2-12 : end , time:10
6pool-1-thread-1-11 : end , time:20
从结果中看,thread-2 是非core线程,执行了 5s,10s这两个任务。就是说非core线程,会去执行队列任务,直到把队列任务处理完。
那么超时的流程是怎样的 ?
下面以thread-2来分析。
runWorker()
1final void runWorker(Worker w) {
2 .......
3 try {
4 while (task != null || (task = getTask()) != null) { // 1
5 .....
6 task.run(); // 2
7 .....
8 }
9 .......
10 } finally {
11 processWorkerExit(w, completedAbruptly); // 3
12 }
13}
14private void processWorkerExit(Worker w, boolean completedAbruptly) {
15 ....
16 workers.remove(w); // 4
17 .....
18}
task != null || getTask() != null
第一次,worker执行完task后,下次循环getTask()去队列中拿 task.拿到了task,执行task
没有拿到task , task == null,(此时队列中没有了任务) . 执行清除线程
将worker从线程池中remove掉。
getTask()
1private Runnable getTask() {
2 ......
3 for (;;) { // 1
4 .....
5 try {
6 Runnable r = timed ? // 2
7 workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : //3
8 workQueue.take(); // 4
9 if (r != null)
10 return r;
11 timedOut = true; // 5
12 } catch (InterruptedException retry) {
13 timedOut = false; // 6
14 }
15 }
16}
线程无限循环去取task
是否有超时限制。取不同的策略
有超时,poll的逻辑 (非core线程)
有task , 返回 task,--> 接runWorker()的第二步。执行task
没有task , 返回 null. --> 接runWorker()的第三步。清除线程
queue中有task,则直接取出task,并返回。不理会keepAliveTime.
queue中没有task , 则线程阻塞等待keepAliveTime的时间 : LockSupport.park(keepAliveTime)
阻塞等待时间结束后,再去取一次task,
不限制超时 (core线程)
queue中有task,返回task
queue中没有task,则线程阻塞 :LockSupport.park(0L) 。永久阻塞,直到被唤醒。
workerQueue.offer(task)
当corePoolSize已经创建满了之后。再有新的task进来时,不是直接交给线程执行的。
而是放到队列中,然后唤醒一个线程,去执行task 。
问题解答:
ThreadPoolExecutor设计的keepAliveTime是通过阻塞线程的方法 。等待keepAliveTime的时长后,还没有task,则将线程清除。
非core线程,会去队列中拿task去执行。直到队列中task被执行完。
再留下一个坑:
当有多个core线程被阻塞时,唤醒操作时?
唤醒全部线程吗 ?为什么 ?
不是的话,唤醒的是哪个线程呢 ?
以上是关于亲 , ThreadPoolExecutor : KeepAliveTime了解一下~的主要内容,如果未能解决你的问题,请参考以下文章
将 InheritableThreadLocal 与 ThreadPoolExecutor - 或 - 不重用线程的 ThreadPoolExecutor 一起使用