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;
}