以下所有代码均来自Netty4.0.31.Final。 ServerBootstrap
的频道为NioServerSocketChannel
。
ServerBootstrap.bind(int)
的主要逻辑在AbstractBootstrap.doBind(SocketAddress)
:
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
...
if (regFuture.isDone()) {
...
doBind0(regFuture, channel, localAddress, promise);
...
} else {
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
...
doBind0(regFuture, channel, localAddress, promise);
}
});
}
}
initAndRegister()
中的代码最终进入AbstractUnsafe.register0(ChannelPromise promise)
:
private void register0(ChannelPromise promise) {
try {
...
boolean firstRegistration = neverRegistered;
doRegister();
...
if (firstRegistration && isActive()) {
pipeline.fireChannelActive();
}
} catch (Throwable t) {
...
}
}
如您所见,此处可能会执行pipeline.fireChannelActive()
。
让我们回到AbstractBootstrap.doBind(SocketAddress)
,doBind0(regFuture, channel, localAddress, promise)
代码最终进入AbstractUnsafe.bind(SocketAddress,ChannelPromise)
:
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
...
boolean wasActive = isActive();
try {
doBind(localAddress);
} catch (Throwable t) {
...
}
if (!wasActive && isActive()) {
invokeLater(new OneTimeTask() {
@Override
public void run() {
pipeline.fireChannelActive();
}
});
}
...
}
如您所见,此处也可能会执行pipeline.fireChannelActive()
。
那么,在创建和绑定一个pipeline.fireChannelActive()
时,NioServerSocketChannel
是否有可能被执行两次?
答案 0 :(得分:1)
除非isActive
能够在你指出的流程中再次将翻转从true翻转为假,再转为真。我认为它只能活跃一次,所以假 - >是的 - >假
您帖子中的相关代码:
boolean firstRegistration = neverRegistered;
...
if (firstRegistration && isActive()) {
pipeline.fireChannelActive(); // isActive must be TRUE
}
...
boolean wasActive = isActive();
...
// If fireChannelActive was fired, then wasActive would be true,
// preventing it from firing again
if (!wasActive && isActive()) {
invokeLater(new OneTimeTask() {
@Override
public void run() {
pipeline.fireChannelActive();