Netty Tool class Hashedwheeltimer source code (three)

Source: Internet
Author: User

Next article (http://my.oschina.net/haogrgr/blog/490266)


8. Worker code for the daytime.

Mainly responsible for the accumulation of tick,  to perform the expiration of tasks. private final class worker implements runnable {     private final set<timeout> unprocessedtimeouts = new  HashSet<Timeout> (    private long tick;    @); Override    public void run ()  {         //initialization Starttime, starttime is just a start time marker,  task deadline is relative to this point in time .         starttime = system.nanotime ();         // Because the Nanotime return value may be 0,  or even a negative number,  so this assignment is 1, timer in the Start method will determine the value,  until not 0 to jump out of the loop .         if  (starttime == 0)  {              starttime = 1;        }         //wake-up blocking thread on the Timer.start () method,  indicates that the completion has started .         Starttimeinitialized.countdown ();         //as long as it's still in the boot state,  always loops          do {          The    //waitfornexttick method mainly calculates the time of the next tick,  and then sleep to the next tick       The       //return value is System.nanotime ()  - startTime,  The timer starts to this tick,   Past Time             final long  Deadline = waitfornexttick ();             if  (deadline > 0)  {//may overflow,  so less than equals 0 regardless of                                   //get index,  principle See Timer's construction method annotation,  equivalent to  tick % wheel.length                 int idx =  (int)   ( Tick & mask);                                    //Remove the Cancel task,  see Hashedwheeltimeout.cancel () method Comments                  processcancelledtasks ();                 //the current tick corresponds to the wheel                 HashedWheelBucket  bucket = wheel[idx];                 //because adding a task is to join the Tim firstEouts Queue,  and this is where the task is removed from the queue,  put into the corresponding bucket                  transfertimeoutstobuckets ();                 //See the comments on the Hashedwheelbucket.expiretimeouts () method                  //is specifically based on the current deadline,  Determine if the characters in the bucket are due,  the task on the expiry of the,  does not expire,  will be the number of people turn minus one .                 //normally,  a bucket in a round,  will only execute once Expiretimeouts method .                  Bucket.expiretimeouts (Deadline);                 //Cumulative tick                 tick++;            }        }  while  (Worker_state_updater.get (hashedwheeltimer.this)  == worker_state_started);         //returns a task that,  has not yet processed while calling stop () .         for  (Hashedwheelbucket bucket: wheel)  {             bucket.cleartimeouts (unprocessedtimeouts);         }        //plus the task of not having time to put in the bucket          for  (;;)  {            hashedwheeltimeout timeout  = timeouts.poll ();            if  ( Timeout == null)  {                break;            }             if  (!timeout.iscancelled ())   {                 Unprocessedtimeouts.add (timeout);             }         }        // It's best to remove the Task        processcancelledtasks () from the Cancel;     }    //the Timer.newtimeout () call into the corresponding bucket when placed into timeouts      Private void transfertimeoutstobuckets ()  {        // tick,  up to 10w task at a time,  prevent too much,  cause the worker thread to stay here for too long.         for   (Int i = 0; i < 100000; i++)  {             Hashedwheeltimeout timeout = timeouts.poll ();             if  (timeout == null)  {                 //all finished.,  Exit cycle                  break;             }            if   (Timeout.state ()  == hashedwheeltimeout.st_cancelled)  {      &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//has not joined the bucket,  the,  continues .                 continue;             }            //calculated  Indicates how many tick            long calculated a task is going through.  = timeout.deadline / tickDuration;             //set the number of rounds that the task will pass              timeout.remainingrounds =  (Calculated - tick)  / wheel.length;             //If the task has been placed in the timeouts queue for a long time,  it has gone through the execution times,  This time using the current tick,  that is put to the current bucket,  and then the method call will be executed .             final long ticks = math.max (Calculated, tick);             int stopIndex =  (int)   (ticks  & mask);//same,  similar to ticks % wheel.length                         //the position of the bucket in wheel indicates that,  after n-wheel,  How many more ticks are needed to execute .            hashedwheelbucket  bucket = wheel[stopindex];             Bucket.addtimeout (timeout);//Add timeout to the list         }     }    //Remove the Cancel task from the queue,  and perform the cancel operation,  See Hashedwheeltimeout.cancel () method comments specifically.     private void processcancelledtasks ()  {         for  (;;)  {            Runnable task =  Cancelledtimeouts.poll ();            if (task == null)  {                 // all processed                 break;            }             try {                 task.run ();             } catch  (throwable t)  {                 if  (logger.iswarnenabled ())  {                     logger.warn ("an exception was thrown while process a  Cancellation task ", &NBSP;T);                 }             }         }    }    /**     *  calculate goal nanotime from starttime and current tick number,      * then wait until that goal has been reached.      *  @return  long.min_value if received a shutdown  request,     * current time otherwise  (With long.min_ VALUE&NBSP;CHANGED&NBSP;BY&NBSP;+1)      */    //sleep,  Until the next tick arrives,  then returns the time between the tick and the start Time     private long waitfornexttick ()  {         //the point in time of the next tick,  is used to calculate the time to sleep         long deadline  = tickDuration *  (tick + 1);         // Loop,  until Hashedwheeltimer is stop,  or to the next tick        for  (;;)  {            //calculates the time required for sleep,  The reason for adding 9999999 and then removing 10000000,  is because the guarantee is a multiple of 10 milliseconds .             final long currenttime = system.nanotime ()  - startTime;             long sleepTimeMs =  (deadline -  currenttime + 999999)  / 1000000;             if  (sleeptimems <= 0)  {//less than or equal to 0,  indicates that the tick has arrived,  return .                 if  (Currenttime == long.min_value)  {                     return -long.max_value; //do not understand,  I do not understand ... Estimation is another nanotime problem .                 } else {                     return currenttime; //return to past time .                 }             }            //  Check if we run on windows, as if thats the case  We will need            // to round the sleeptime as workaround for  a bug that only affect             // the JVM if it runs on windows.             //              See https://github.com/netty/netty/issues/356             if  (Platformdependent.iswindows ())  {//not much to say,  a word,  dick                  sleepTimeMs =  sleeptimems / 10 * 10;             }            try {        &nbsP;        thread.sleep (Sleeptimems);//Sleep              } catch  (interruptedexception ignored)  {                 //when Timer.stop is called,   Exit                 if   (Worker_state_updater.get (hashedwheeltimer.this)  == worker_state_shutdown)  {                      return long.min_value;                 }            }         }    }    public Set<Timeout>  unprocessedtimeouts () {        return collections.unmodifiableset ( unprocessedtimeouts);     }}


Finally finished, the specific look at the comments, very detailed comments.



9. Remarks.

While looking at the code, most of them are good, but some of the code is confusing, for example

StartTime = System.nanotime (); if (startTime = = 0) {//We use 0 as a indicator for the uninitialized value here, so Ma    Ke sure it ' s not 0 when initialized. StartTime = 1;} StartTime is volatile, and then there is no other place to modify the StartTime, why here also to determine whether it is 0 ...

Then I went to the group and asked, the last to locate is the problem of Nanotime, the API document that it even negative numbers may return ~ ~ ~


Great God (Beijing-Rookie years) affixed to the Nanotime implementation.

Jlong os::javatimenanos ()  {  if  (Linux::supports_monotonic_clock ())  {     struct timespec tp;    int status = linux:: Clock_gettime (CLOCK_MONOTONIC,&NBSP;&AMP;TP);     assert (status == 0,  " Gettime error ");     jlong result = jlong (tp.tv_sec)  *  (1000  * 1000 * 1000)  + jlong (tp.tv_nsec);    return result;   } else {    timeval time;    int  Status = gettimeofday (&time, null);     assert (Status != -1,   "Linux error");     jlong usecs = jlong (time.tv_sec)  *  (1000 * 1000)  + jlong (time.tv_usec);    return 1000 *  usecs;  }}

BEIJING-Rookie years: Read the code originally this Clock_gettime function may occur time wrapping

BEIJING-Rookie for years : then the nanosecond becomes 0.

Beijing-Rookie for many years : However, it takes a long time

Beijing-Rookie for many years : time increments to a certain point, then it overflows and starts at 0.

Beijing-Rookie for many years : Timespec This inside seconds and nanoseconds are stored separately

Beijing-Rookie for many years : Just to prolong the chance of wrapping up.

Beijing-Rookie for many years : Else that branch is the implementation of Currenttimemillis ()

Beijing-Rookie for many years : Just nanosecond level

BEIJING-Rookie for many years : like the currenttimemillis algorithm, performance is slower



10. Summary.

Do not have too much time-consuming operation in the task, otherwise it will block the worker thread, cause the tick is not allowed.

Wheel Timer, is indeed a very ingenious algorithm, Netty implementation of Hashedwheeltimer is also through the great God's ultimate optimization.

Netty Tool class Hashedwheeltimer source code (three)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.