接着上面的流程,现在请求到了Poller的#register()方法。
public
void
register(
final
NioChannel socket)
{
socket.setPoller(
this
);
//
KeyAttachment是对NioChannel信息的包装,同样是非GC
KeyAttachment key
=
keyCache.poll();
final
KeyAttachment ka
=
key
!=
null
?
key :
new
KeyAttachment(socket);
ka.reset(
this
, socket, getSocketProperties().getSoTimeout());
ka.setKeepAliveLeft(NioEndpoint.
this
.getMaxKeepAliveRequests());
//
PollerEvent的初始化,非GC Again
PollerEvent r
=
eventCache.poll();
//
this is what OP_REGISTER turns into.
//
读取数据的事件
ka.interestOps(SelectionKey.OP_READ);
if
(r
==
null
)
r
=
new
PollerEvent(socket, ka, OP_REGISTER);
else
r.reset(socket, ka, OP_REGISTER);
//
把事件加到Poller
addEvent(r);
}
public
void
addEvent(Runnable event)
{
//
把事件加入到队列中
events.offer(event);
//
++wakeupCounter
if
(wakeupCounter.incrementAndGet()
==
0
) selector.wakeup();
}
其实也挺好懂的,就是把NioChannel作为OP_REGISTER事件注册到Poller,这样在Poller的#run()方法中就可以对加入Poller的事件进行处理了。
public
void
run()
{
while
(running)
{
try
{
while
(paused
&&
(
!
close))
{
try
{
Thread.sleep(
100
);
}
catch
(InterruptedException e)
{
//
Ignore
}
}
boolean
hasEvents
=
false
;
hasEvents
=
(hasEvents
|
events());
//
Time to terminate?
if
(close)
{
timeout(
0
,
false
);
break
;
}
try
{
if
(
!
close)
{
if
(wakeupCounter.get()
>
0
)
{
//
立刻返回 I/O 就绪的那些通道的键
keyCount
=
selector.selectNow();
}
else
{
keyCount
=
selector.keys().size();
//
这里把wakeupCounter设成-1,在addEvent的时候就会唤醒selector
wakeupCounter.set(
-
1
);
//
使用阻塞的方式
keyCount
=
selector.select(selectorTimeout);
}
wakeupCounter.set(
0
);
}
if
(close)
{
timeout(
0
,
false
);
selector.close();
break
;
}
}
catch
(NullPointerException x)
{
//
sun bug 5076772 on windows JDK 1.5
if
(log.isDebugEnabled())
log.debug(
"
Possibly encountered sun bug 5076772 on windows JDK 1.5
"
, x);
if
(wakeupCounter
==
null
||
selector
==
null
)
throw
x;
continue
;
}
catch
(CancelledKeyException x)
{
//
sun bug 5076772 on windows JDK 1.5
if
(log.isDebugEnabled())
log.debug(
"
Possibly encountered sun bug 5076772 on windows JDK 1.5
"
, x);
if
(wakeupCounter
==
null
||
selector
==
null
)
throw
x;
continue
;
}
catch
(Throwable x)
{
ExceptionUtils.handleThrowable(x);
log.error(
""
, x);
continue
;
}
//
either we timed out or we woke up, process events first
if
(keyCount
==
0
)
hasEvents
=
(hasEvents
|
events());
Iterator
<
SelectionKey
>
iterator
=
keyCount
>
0
?
selector.selectedKeys().iterator()
:
null
;
//
Walk through the collection of ready keys and dispatch
//
any active event.
while
(iterator
!=
null
&&
iterator.hasNext())
{
SelectionKey sk
=
iterator.next();
//
这里的KeyAttachment实在#register()方法中注册的
KeyAttachment attachment
=
(KeyAttachment) sk.attachment();
attachment.access();
iterator.remove();
//
继续流程
processKey(sk, attachment);
}
//
while
//
process timeouts
timeout(keyCount, hasEvents);
if
(oomParachute
>
0
&&
oomParachuteData
==
null
)
checkParachute();
}
catch
(OutOfMemoryError oom)
{
try
{
oomParachuteData
=
null
;
releaseCaches();
log.error(
""
, oom);
}
catch
(Throwable oomt)
{
try
{
System.err.println(oomParachuteMsg);
oomt.printStackTrace();
}
catch
(Throwable letsHopeWeDontGetHere)
{
ExceptionUtils.handleThrowable(letsHopeWeDontGetHere);
}
}
}
}
//
while
synchronized
(
this
)
{
this
.notifyAll();
}
stopLatch.countDown();
}
这个方法有2个方法需要关注一下:#events()和#processKey():
public
boolean
events()
{
boolean
result
=
false
;
//
synchronized (events) {
Runnable r
=
null
;
//
返回是事件队列中是否有事件
result
=
(events.size()
>
0
);
while
((r
=
events.poll())
!=
null
)
{
try
{
//
执行KeyEvent的#run()
r.run();
if
(r
instanceof
PollerEvent)
{
((PollerEvent) r).reset();
//
对KeyEvent进行回收
eventCache.offer((PollerEvent) r);
}
}
catch
(Throwable x)
{
log.error(
""
, x);
}
}
//
events.clear();
//
}
return
result;
}
这里执行了SocketChannel对应的KeyEvent的#run()方法,在这个方法里给SocketChannel注册了OP_READ:
public
void
run()
{
if
(interestOps
==
OP_REGISTER)
{
try
{
//
给SocketChannel注册OP_READ
socket.getIOChannel().register(socket.getPoller().getSelector(), SelectionKey.OP_READ,
key);
}
catch
(Exception x)
{
log.error(
""
, x);
}
}
else
{
//
这里应该是对comet进行支持的,暂时先不看
......
}
//
end if
}
//
run
第二个是#processKey()方法,里边的很多流程我现在不是很关心,都略去了,
protected
boolean
processKey(SelectionKey sk, KeyAttachment attachment)
{
boolean
result
=
true
;
try
{
if
(close)
{
cancelledKey(sk, SocketStatus.STOP,
false
);
}
else
if
(sk.isValid()
&&
attachment
!=
null
)
{
attachment.access();
//
make sure we don't time out valid sockets
sk.attach(attachment);
//
cant remember why this is here
NioChannel channel
=
attachment.getChannel();
if
(sk.isReadable()
||
sk.isWritable())
{
if
(attachment.getSendfileData()
!=
null
)
{
processSendfile(sk, attachment,
true
,
false
);
}
else
if
(attachment.getComet())
{
//
这里应该是对comet的支持
......
}
else
{
//
这个分支是现在比较关心的
if
(isWorkerAvailable())
{
//
这个好像还没实现
//
这个#unreg()很巧妙,防止了通道对同一个事件不断select的问题
unreg(sk, attachment, sk.readyOps());
boolean
close
=
(
!
processSocket(channel,
null
,
true
));
color: #000
分享到:
相关推荐
赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....
赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...
赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...
赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....
赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...
赠送源代码:httpcore-nio-4.4.6-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.6-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...
8. **性能优化**:可以通过调整`server.xml`中的线程池设置、启用NIO连接器、增加JVM堆大小等方式优化Tomcat性能。 9. **集成其他应用服务器**:Tomcat可以与其他Java EE服务器(如JBoss、WebLogic)一起使用,作为...
Apache Tomcat 是一个开源软件应用服务器,主要用于部署和运行Java Servlet和JavaServer Pages(JSP)应用程序。这个压缩包文件 "apache-tomcat-8.5.97-windows-x.zip" 包含了Apache Tomcat 8.5.97 版本在Windows...
**Apache Tomcat 8源代码解析** Apache Tomcat是一款开源的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是许多Web应用开发者的重要工具。Tomcat 8是其发展的一个重要版本,引入了许多新...
赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....
这个源代码压缩包提供了Tomcat6的完整源码,对于开发者来说,深入理解其内部工作原理、优化性能或者定制功能都具有极大的价值。下面将详细介绍Tomcat6的一些关键知识点。 1. **Servlet容器**: Tomcat作为一个...
在本文中,我们将深入探讨`apache-tomcat-7.0.88-src.tar`这个源代码包,了解其核心组件、工作原理以及如何通过源代码学习和定制Tomcat。 首先,`apache-tomcat-7.0.88-src.tar`是一个包含Apache Tomcat 7.0.88版本...
赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:...
4. **NIO2 Connector**:Tomcat 9.0引入了NIO2连接器,提供非阻塞I/O,适用于高并发场景,可以提高服务器性能。 5. **JAR Scanning**:为提高安全性,Tomcat现在可以扫描JAR文件中的特定元素,如TLDs,以便自动注册...
《深入剖析Tomcat7源代码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用规范,包括Servlet、JSP和EL(Expression Language)等。本资源包含Tomcat7的源代码以及运行所需的jar包,...
7. **性能调优**: Tomcat的性能可以通过调整各种参数进行优化,例如增大最大线程数、设置连接器超时、使用NIO连接器等。此外,还可以通过使用JVM的内存调优和垃圾回收策略来提升性能。 8. **安全性**: Tomcat提供了...
Apache Tomcat 9.0.74 是一个广泛使用的开源软件,它是一个实现了Java Servlet、JavaServer Pages(JSP)和Java EE的Web应用程序容器。这个版本是专门为Windows x64平台设计的,确保在64位操作系统上高效运行。在...
赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....
在这个"网络编程(socket、NIO、mina)---demo"的主题中,我们将深入探讨三个关键概念:Socket编程、非阻塞I/O(Non-blocking I/O,简称NIO)以及Apache Mina框架。这些技术广泛应用于构建高性能、高并发的网络应用...
Apache Tomcat是一款开源的Java应用服务器,主要用于运行Java Servlet和JavaServer Pages(JSP)技术。这个"apache-tomcat-9.0.55-windows-x64位官方版"是Tomcat的9.0.55版本,针对64位Windows操作系统设计。在这一...