Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the startup process of Netty NioEventLoop?

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "how the Netty NioEventLoop startup process is". In the operation of actual cases, many people will encounter such a dilemma. Then let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Start

Analyze the execute () interface of NioEventLoop. The main logic is as follows:

Add a task queue

Bind the current thread to the EventLoop

Call the run () method of EventLoop

Private static void doBind0 (final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) {/ / perform channel binding Task channel.eventLoop () .execute (new Runnable () {@ Override public void run () {if (regFuture.isSuccess ()) {/ / channel binding channel.bind (localAddress) via eventLoop Promise) .addListener (ChannelFutureListener.CLOSE_ON_FAILURE) } else {promise.setFailure (regFuture.cause ());});}

Trace down to the execute interface in SingleThreadEventExecutor, as follows:

@ Overridepublic void execute (Runnable task) {if (task = = null) {throw new NullPointerException ("task");} / determine whether the current runtime thread is consistent with the thread bound in EventLoop / / Thread is not bound here, so first return false boolean inEventLoop = inEventLoop (); / / add the task to the task queue, which is the MpscQueue we mentioned when EventLoop was created. AddTask (task); if (! inEventLoop) {/ / start thread startThread (); if (isShutdown () & & removeTask (task)) {reject ();}} if (! addTaskWakesUp & & wakesUpForTask (task)) {wakeup (inEventLoop);}}

Start the thread interface:

Private void startThread () {/ / status comparison. At the beginning, state = 1. After true if (state = = ST_NOT_STARTED) {/ / cs operation, the state status is set to 2 if (STATE_UPDATER.compareAndSet (this, ST_NOT_STARTED, ST_STARTED)) {try {/ / start interface doStartThread () } catch (Throwable cause) {STATE_UPDATER.set (this, ST_NOT_STARTED); PlatformDependent.throwException (cause);} / / execute thread startup method private void doStartThread () {/ / assert that SingleThreadEventExecutor is not yet bound Thread assert thread = = null / / executor execute task executor.execute (new Runnable () {@ Override public void run () {/ / bind SingleThreadEventExecutor (in our case, NioEventLoop) to the current thread thread = Thread.currentThread (); if (interrupted) {thread.interrupt () } / / set the status to false boolean success = false; / / update the execution time of the last task updateLastExecutionTime (); try {/ / call the run method of NioEventLoop to execute SingleThreadEventExecutor.this.run (); success = true } catch (Throwable t) {logger.warn ("Unexpected exception from an event executor:", t);} finally {...}});} execute

Calling the run method in NioEventLoop, through an infinite for loop, mainly does the following three things:

Round robin event: select (wakenUp.getAndSet (false))

Handling the Icano event: processSelectedKeys

Run the Task task: runAllTasks

@ Overrideprotected void run () {for (;;) {try {switch (selectStrategy.calculateStrategy (selectNowSupplier, hasTasks () {case SelectStrategy.CONTINUE: continue Case SelectStrategy.SELECT: / / rotation training to detect the selector O event / / wakenUp in order to mark whether the selector is in a wake-up state, each select operation is set to false, that is, the unawakened state. Select (wakenUp.getAndSet (false)); / / 'wakenUp.compareAndSet (false, true)' is always evaluated before calling 'selector.wakeup ()' to reduce wake-up overhead / (Selector.wakeup () is a very performance-consuming operation.) / but there is a race condition for this method. Trigger a race condition when "wakeup" is set to true too early / / in the following two cases, "wakenUp" is prematurely set to true: / / 1) Selector in 'wakenUp.set (false)' and 'selector.select (...)' Was awakened between. (BAD) / / 2) Selector in 'selector.select (...)' Awakened with'if (wakenUp.get ()) {...}'. (OK) / / in the first case, 'wakenUp' is set to true, followed by' selector.select (...) 'will wake up immediately. Until 'wakenUp' is set to false,'wakenUp.compareAndSet (false,true) again in the next round' will fail, so any attempt to wake up the selector will also fail, resulting in the following 'selector.select (..)' call to block unnecessary. / / to solve this problem, if wakenUp is true immediately after the selector.select (...) operation, we will wake up selector again. It is inefficient because it wakes up selectors in the first case (BAD-need to wake up) and the second case (OK-no need to wake up). If (wakenUp.get ()) {selector.wakeup ();} / / fall through default:} cancelledKeys = 0; needsToSelectAgain = false; / / ioRatio represents the ratio of the time taken to process the Iapo event to the specific task event. / / ioRatio defaults to 50 final int ioRatio = this.ioRatio; if (ioRatio = 100) {try {/ / handling the processSelectedKeys ();} finally {/ / processing task queue runAllTasks () }} else {/ / start time of processing IO event final long ioStartTime = System.nanoTime (); try {/ / processing Icano event processSelectedKeys () } finally {/ / record the time spent by io final long ioTime = System.nanoTime ()-ioStartTime; / / process the task queue, and set the maximum timeout runAllTasks (ioTime * (100-ioRatio) / ioRatio) } catch (Throwable t) {handleLoopException (t);} / / Always handle shutdown even if the loop processing threw an exception. Try {if (isShuttingDown ()) {closeAll (); if (confirmShutdown ()) {return;} catch (Throwable t) {handleLoopException (t);} Round-robin detection of private void select (boolean oldWakenUp) throws IOException {Selector selector = this.selector The try {/ / select operation count int selectCnt = 0; / / record the current system time long currentTimeNanos = System.nanoTime (); / / the delayNanos method is used to calculate the scheduled task queue. The deadline / / selectDeadLineNanos of the most recent task represents the maximum deadline long selectDeadLineNanos = currentTimeNanos + delayNanos (currentTimeNanos) that cannot be exceeded by the current select operation; for ( ) {/ / calculate the timeout to determine whether the timeout long timeoutMillis = (selectDeadLineNanos-currentTimeNanos + 500000L) / 1000000L; / / if timeoutMillis

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report