netty程序,使用shutdownGracefully退出。退出前会把队列中的消息发送完,释放channel,多路复用器的去注册,清空定时器任务等。
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
EventExecutor[] var6 = this.children;
int var7 = var6.length;
for(int var8 = 0; var8 < var7; ++var8) {
EventExecutor l = var6[var8];
l.shutdownGracefully(quietPeriod, timeout, unit);
}
return this.terminationFuture();
}
shutdownGracefully实现在NioEventLoop的父类SingleThreadEventExecutor中,
首先是改变state,为了防止并发问题,这里是netty 4,采用的原子类自旋的方式避免加锁。
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
ObjectUtil.checkPositiveOrZero(quietPeriod, "quietPeriod");
if(timeout < quietPeriod) {
throw new IllegalArgumentException("timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
} else {
ObjectUtil.checkNotNull(unit, "unit");
if(this.isShuttingDown()) {
return this.terminationFuture();
} else {
boolean inEventLoop = this.inEventLoop();
boolean wakeup;
int oldState;
int newState;
do {
if(this.isShuttingDown()) {
return this.terminationFuture();
}
wakeup = true;
oldState = this.state;
if(inEventLoop) {
newState = 3;
} else {
switch(oldState) {
case 1:
case 2:
newState = 3;
break;
default:
newState = oldState;
wakeup = false;
}
}
} while(!STATE_UPDATER.compareAndSet(this, oldState, newState));
this.gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
this.gracefulShutdownTimeout = unit.toNanos(timeout);
if(this.ensureThreadStarted(oldState)) {
return this.terminationFuture;
} else {
if(wakeup) {
this.taskQueue.offer(WAKEUP_TASK);
if(!this.addTaskWakesUp) {
this.wakeup(inEventLoop);
}
}
return this.terminationFuture();
}
}
}
}
唤醒selector,由NioEventLoop实现。
protected void wakeup(boolean inEventLoop) {
if(!inEventLoop && this.nextWakeupNanos.getAndSet(-1L) != -1L) {
this.selector.wakeup();
}
}
状态改变之后, run方法中检测到状态变化,执行closeAll方法
if(this.isShuttingDown()) {
this.closeAll();
if(this.confirmShutdown()) {
return;
}
}
获取channel,如果是nioChannel,则调用unsafe的close方法。
private void closeAll() {
this.selectAgain();
Set<SelectionKey> keys = this.selector.keys();
Collection<AbstractNioChannel> channels = new ArrayList(keys.size());
Iterator var3 = keys.iterator();
while(var3.hasNext()) {
SelectionKey k = (SelectionKey)var3.next();
Object a = k.attachment();
if(a instanceof AbstractNioChannel) {
channels.add((AbstractNioChannel)a);
} else {
k.cancel();
NioTask<SelectableChannel> task = (NioTask)a;
invokeChannelUnregistered(task, k, (Throwable)null);
}
}
var3 = channels.iterator();
while(var3.hasNext()) {
AbstractNioChannel ch = (AbstractNioChannel)var3.next();
ch.unsafe().close(ch.unsafe().voidPromise());
}
}
AbstractChannel中的内部类AbstractUnsafe的close和voidPromise方法
public final void close(ChannelPromise promise) {
this.assertEventLoop();
ClosedChannelException closedChannelException = new ClosedChannelException();
this.close(promise, closedChannelException, closedChannelException, false);
}
public final ChannelPromise voidPromise() {
this.assertEventLoop();
return AbstractChannel.this.unsafeVoidPromise;
}
判断当前链路中是否有未发送的消息,如果有则稍后再取消注册,将任务放到task中。
关闭链路
private void close(final ChannelPromise promise, final Throwable cause, final ClosedChannelException closeCause, final boolean notify) {
if(promise.setUncancellable()) {
if(AbstractChannel.this.closeInitiated) {
if(AbstractChannel.this.closeFuture.isDone()) {
this.safeSetSuccess(promise);
} else if(!(promise instanceof VoidChannelPromise)) {
AbstractChannel.this.closeFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
promise.setSuccess();
}
});
}
} else {
AbstractChannel.this.closeInitiated = true;
final boolean wasActive = AbstractChannel.this.isActive();
final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
//清空发送队列
this.outboundBuffer = null;
Executor closeExecutor = this.prepareToClose();
if(closeExecutor != null) {
closeExecutor.execute(new Runnable() {
public void run() {
try {
AbstractUnsafe.this.doClose0(promise);
} finally {
AbstractUnsafe.this.invokeLater(new Runnable() {
public void run() {
if(outboundBuffer != null) {
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(closeCause);
}
AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
}
});
}
}
});
} else {
try {
this.doClose0(promise);
} finally {
if(outboundBuffer != null) {
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(closeCause);
}
}
if(this.inFlush0) {
this.invokeLater(new Runnable() {
public void run() {
AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
}
});
} else {
//触发链路关闭通知事件,从多路复用器取消selectionKey
this.fireChannelInactiveAndDeregister(wasActive);
}
}
}
}
}
从多路复用器取消selectionKey
protected void doDeregister() throws Exception {
this.eventLoop().cancel(this.selectionKey());
}
关闭链路之后
protected boolean confirmShutdown() {
if(!this.isShuttingDown()) {
return false;
} else if(!this.inEventLoop()) {
throw new IllegalStateException("must be invoked from an event loop");
} else {
this.cancelScheduledTasks();
if(this.gracefulShutdownStartTime == 0L) {
this.gracefulShutdownStartTime = ScheduledFutureTask.nanoTime();
}
if(!this.runAllTasks() && !this.runShutdownHooks()) {
long nanoTime = ScheduledFutureTask.nanoTime();
if(!this.isShutdown() && nanoTime - this.gracefulShutdownStartTime <= this.gracefulShutdownTimeout) {
if(nanoTime - this.lastExecutionTime <= this.gracefulShutdownQuietPeriod) {//若没有达到指定时间,则先不退出
this.taskQueue.offer(WAKEUP_TASK);
try {
Thread.sleep(100L);
} catch (InterruptedException var4) {
;
}
return false;
} else {
return true;
}
} else {
return true;
}
} else if(this.isShutdown()) {
return true;
} else if(this.gracefulShutdownQuietPeriod == 0L) {
return true;
} else {
this.taskQueue.offer(WAKEUP_TASK);
return false;
}
}
}
执行尚在taskQueue中的任务,
do {
// PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue;
fetchedAll = this.fetchFromScheduledTaskQueue();//取出队列scheduledTaskQueue中所有的任务,放到taskQueue中。
if(this.runAllTasksFrom(this.taskQueue)) {
ranAtLeastOne = true;
}
} while(!fetchedAll);
执行taskQueue中的所有任务
//Queue<Runnable> taskQueue
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
Runnable task = pollTaskFrom(taskQueue);
if(task == null) {
return false;
} else {
do {
safeExecute(task);
task = pollTaskFrom(taskQueue);
} while(task != null);
return true;
}
}
执行注册到nioeventLoop中的任务
private boolean runShutdownHooks() {
boolean ran = false;
while(!this.shutdownHooks.isEmpty()) {
List<Runnable> copy = new ArrayList(this.shutdownHooks);
this.shutdownHooks.clear();
Iterator var3 = copy.iterator();
while(var3.hasNext()) {
Runnable task = (Runnable)var3.next();
try {
task.run();
} catch (Throwable var9) {
logger.warn("Shutdown hook raised an exception.", var9);
} finally {
ran = true;
}
}
}
if(ran) {
this.lastExecutionTime = ScheduledFutureTask.nanoTime();
}
return ran;
}