@Override protectedvoidrun(){ int selectCnt = 0; //使用死循环进行轮询 for (;;) { try { int strategy; try { //hasTasks为ture执行selectNow(),否则返回SelectStrategy.SELECT,会优先处理I/O事件 strategy = selectStrategy.calculatStrategy(selectNowSupplier, hasTasks()); switch (strategy) { case SelectStrategy.CONTINUE: continue;
case SelectStrategy.BUSY_WAIT: // fall-through to SELECT since the busy-wait is not supported with NIO //返回SELECT表示当前没有任务 case SelectStrategy.SELECT: long curDeadlineNanos = nextScheduledTaskDeadlineNanos(); if (curDeadlineNanos == -1L) { curDeadlineNanos = NONE; // nothing on the calendar } nextWakeupNanos.set(curDeadlineNanos); try { //再次判断是否有任务,没有时执行Selector.selectNow()方法获取I/O事件, //没有时selectNow会阻塞线程,阻塞时间通过curDeadlineNanos控制 if (!hasTasks()) { //没有任务时执行Selector.selectNow()查询当前的I/O事件 strategy = select(curDeadlineNanos); } } finally { // This update is just to help block unnecessary selector wakeups // so use of lazySet is ok (no race condition) nextWakeupNanos.lazySet(AWAKE); } // fall through default: } } catch (IOException e) { // If we receive an IOException here its because the Selector is messed up. Let's rebuild // the selector and retry. https://github.com/netty/netty/issues/8566 rebuildSelector0(); selectCnt = 0; handleLoopException(e); continue; }
selectCnt++; cancelledKeys = 0; needsToSelectAgain = false; //IO事件的比率 finalint ioRatio = this.ioRatio; boolean ranTasks; //为100时立即处理I/O事件 if (ioRatio == 100) { try { //通过SelectNow获取的事件数量 if (strategy > 0) { //执行I/O事件 processSelectedKeys(); } } finally { // 执行完I/O事件后执行一次任务 ranTasks = runAllTasks(); } //ioRatio没有100时且当前有I/O事件时 } elseif (strategy > 0) { finallong ioStartTime = System.nanoTime(); try { //执行I/O事件 processSelectedKeys(); } finally { // 通过ioRatio与I/O事件执行时间计算出任务执行超时时间 finallong ioTime = System.nanoTime() - ioStartTime; ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio); } //没有I/O事件时将时间全部分配给任务执行 } else { ranTasks = runAllTasks(0); // This will run the minimum number of tasks } //通过selectCnt计数解决多次selectNow后没有I/O事件的问题 if (ranTasks || strategy > 0) { //执行过任务或者I/O事件认为是有效的就重置selectCnt if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS && logger.isDebugEnabled()) { logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.", selectCnt - 1, selector); } selectCnt = 0; //无效时rebuild selector } elseif (unexpectedSelectorWakeup(selectCnt)) { // Unexpected wakeup (unusual case) selectCnt = 0; } } catch (CancelledKeyException e) { // Harmless exception - log anyway if (logger.isDebugEnabled()) { logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?", selector, e); } } catch (Error e) { throw (Error) e; } catch (Throwable t) { handleLoopException(t); } finally { // Always handle shutdown even if the loop processing threw an exception. try { if (isShuttingDown()) { closeAll(); if (confirmShutdown()) { return; } } } catch (Error e) { throw (Error) e; } catch (Throwable t) { handleLoopException(t); } } } }