NioEndpoint
设计模式
- 模板设计模式 ( NioEndpoint extends AbstractEndpoint)
线程模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| Acceptor ( getPoller0().register(channel); )
-> poller register() add(NioChannel , SelectionKey) (for in NioChannelList)
-> selector.selectedKeys() 判断 channel 状态 可写 可读
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
|
Tomcat 线程池
重写了 LinkedBlockingQueue ,TaskQueue
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
| class TaskQueue extends LinkedBlockingQueue{
@Override
public boolean offer(Runnable o) {
if (parent==null) {
return super.offer(o);
}
if (parent.getPoolSize() == parent.getMaximumPoolSize()) {
return super.offer(o);
}
if (parent.getSubmittedCount()<=(parent.getPoolSize())) {
return super.offer(o);
}
if (parent.getPoolSize()<parent.getMaximumPoolSize()) {
return false;
}
return super.offer(o);
}
}
|
重写 offer 方法,没有达到线程池的最大线程数,则返回false ,继续创建线程,如果大于则加入阻塞队列,队列满了 则抛出 拒绝策略,如果 已提交的任务数小于当前线程池中的线程数 则加入队列(不创建新的线程)
Tomcat 线程池扩展了原生的 ThreadPoolExecutor,通过重写 execute 方法实现了自己的任务处理逻辑:
● 前 corePoolSize 个任务时,来一个任务就创建一个新线程。
● 还有任务提交,直接放到队列,队列满了,但是没有达到最大线程池数则创建临时线程救火。
● 线程总线数达到 maximumPoolSize ,继续尝试把任务放到队列中。如果队列也满了,插入任务失败,才执行拒绝策略。
最大的差别在于 Tomcat 在线程总数达到最大数时,不是立即执行拒绝策略,而是再尝试向任务队列添加任务,添加失败后再执行拒绝策略。