简要的介绍了Jetty的启动流程。对象池是一个很新颖的概念,与线程池有所区别。
创建Server
初始化线程池
使用QueuedThreadpool实现SizedThreadPool
初始化ServerConnector
- 初始化SecheduledExecutorScheduler
初始化ByteBufferPool (相当于对象池,减少GC),创建对象的效率是很高的,回收很低。不能使用sycronized同步,效率太低,必须使用无锁。
ArrayByteBufferPool。大小不一定相同,池中保存很多大小不同的对象。
列外处理:如果社情的ByteBuffer过大或者过小无法在Pool中满足,则可以申请陈宫,但无法归还给Pool1
2
3
4
5
6
7
8public ArrayByteBufferPool(int minSize,int increment,int maxSize)
direct[] =
indirect[] =
Queue<ByteBuffer> = new ConcurrentLinkedQueue<>();
//1取得合适的Bucket 2从Bucket中取得ByteBuffer 3不存在创建
acquire()
//1取得合适的Bucket 2清空Buffer 3归还Pool
release()ConnectionFactory维护
用于创建链接,比如Accept后,需要创建一个表示链接的对象获取cpu数量
1
cores = Runtime.getRuntime().availableProcessors();
更新acceptor数量
1
acceptors = Math.max(1,Math.min(4,cores/8));
创建acceptor线程组
- 初始化ServerConnectorManger
继承自
保存selector线程数量1
Math.min(4,Runtime.getRuntime().availableProcessors()/2)
设置port
关联Server和Connector
Server.start
设置启动状态
启动过程doStart
- 注册ShutdownMonitor 远程控制接口
- 获取线程池
- 设置selector数量
累计所有connector的需要 - 计算所需的所有线程数量
如果大于默认的200则中断程序 - 维护Bean
启动QueudThreadPool:创建线程 设置线程的属性 启动线程
启动WebAppContext - 启动Connector
取得ConnectionFactory
创建selector线程并启动
创建Acceptor线程 设置线程名字优先级,将线程放入acceptors 监听端口
没有Acceptor的情况启动完毕
Http请求
Accept成功
- 设置为非阻塞模式
- 配置Socket
- 正式处理
选择可用ManagedSelector线程1
2
3
4
5
6private ManagedSelector chooseSelector(){
//没有使用原子整数,不必担心因为多线程安全导致的问题
long s = _selectorIndex++;
int index = (int) (s % getSelectorCount());
return _selectors[index];
}
ManagedSelector处理
提交任务 加入到ConcurrentArrayQueue队列
请求处理
ManagedSelector.run()1
2
3
4
5private void runChanges(){
Runnable change;
while((change = _changes.poll())!=null)
runChange(change);
}
select()
处理SelectionKey