设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 数据 手机
当前位置: 首页 > 服务器 > 系统 > 正文

Tomcat 中的 NIO 源码分析(4)

发布时间:2020-01-07 12:09 所属栏目:52 来源:站长网
导读:到这里,我们启动了工作线程池、 poller 线程组、acceptor 线程组。同时,工作线程池初始就已经启动了 10 个线程。我们用 jconsole 来看看此时的线程,请看下图: 从 jconsole 中,我们可以看到,此时启动了 BlockP

到这里,我们启动了工作线程池、 poller 线程组、acceptor 线程组。同时,工作线程池初始就已经启动了 10 个线程。我们用 jconsole 来看看此时的线程,请看下图:

Tomcat 中的 NIO 源码分析

从 jconsole 中,我们可以看到,此时启动了 BlockPoller、worker、poller、acceptor、AsyncTimeout,大家应该都已经清楚了每个线程是哪里启动的吧。

Tomcat 中并没有 Worker 这个类,此名字是我瞎编。

此时,我们还是不知道 acceptor、poller 甚至 worker 到底是干嘛的,下面,我们从 acceptor 线程开始看起。

Acceptor

它的结构非常简单,在构造函数中,已经把 endpoint 传进来了,此外就只有 threadName 和 state 两个简单的属性。

private final AbstractEndpoint<?,U> endpoint; 

private String threadName; 

protected volatile AcceptorState state = AcceptorState.NEW; 

 

publicAcceptor(AbstractEndpoint<?,U> endpoint) { 

this.endpoint = endpoint; 

threadName 就是一个线程名字而已,Acceptor 的状态 state 主要是随着 endpoint 来的。

public enum AcceptorState { 

NEW, RUNNING, PAUSED, ENDED 

我们直接来看 acceptor 的 run 方法吧:

Acceptor # run

@Override 

public voidrun { 

 

int errorDelay = 0; 

 

// 只要 endpoint 处于 running,这里就一直循环 

while (endpoint.isRunning) { 

 

// 如果 endpoint 处于 pause 状态,这边 Acceptor 用一个 while 循环将自己也挂起 

while (endpoint.isPaused && endpoint.isRunning) { 

state = AcceptorState.PAUSED; 

try { 

Thread.sleep(50); 

} catch (InterruptedException e) { 

// Ignore 

// endpoint 结束了,Acceptor 自然也要结束嘛 

if (!endpoint.isRunning) { 

break; 

state = AcceptorState.RUNNING; 

 

try { 

// 如果此时达到了最大连接数(之前我们说过,默认是10000),就等待 

endpoint.countUpOrAwaitConnection; 

 

// Endpoint might have been paused while waiting for latch 

// If that is the case, don't accept new connections 

if (endpoint.isPaused) { 

continue; 

 

U socket = ; 

try { 

// 这里就是接收下一个进来的 SocketChannel 

// 之前我们设置了 ServerSocketChannel 为阻塞模式,所以这边的 accept 是阻塞的 

socket = endpoint.serverSocketAccept; 

} catch (Exception ioe) { 

// We didn't get a socket 

endpoint.countDownConnection; 

if (endpoint.isRunning) { 

// Introduce delay if necessary 

errorDelay = handleExceptionWithDelay(errorDelay); 

// re-throw 

throw ioe; 

} else { 

break; 

// accept 成功,将 errorDelay 设置为 0 

errorDelay = 0; 

 

if (endpoint.isRunning && !endpoint.isPaused) { 

// setSocketOptions 是这里的关键方法,也就是说前面千辛万苦都是为了能到这里进行处理 

if (!endpoint.setSocketOptions(socket)) { 

// 如果上面的方法返回 false,关闭 SocketChannel 

endpoint.closeSocket(socket); 

} else { 

// 由于 endpoint 不 running 了,或者处于 pause 了,将此 SocketChannel 关闭 

endpoint.destroySocket(socket); 

} catch (Throwable t) { 

ExceptionUtils.handleThrowable(t); 

String msg = sm.getString("endpoint.accept.fail"); 

// APR specific. 

// Could push this down but not sure it is worth the trouble. 

if (t instanceof Error) { 

Error e = (Error) t; 

if (e.getError == 233) { 

// Not an error on HP-UX so log as a warning 

// so it can be filtered out on that platform 

// See bug 50273 

log.warn(msg, t); 

} else { 

log.error(msg, t); 

} else { 

log.error(msg, t); 

state = AcceptorState.ENDED; 

大家应该发现了,Acceptor 绕来绕去,都是在调用 NioEndpoint 的方法,我们简单分析一下这个。

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读