"Original" Timer and system time

Source: Internet
Author: User

Problem:
--------------------------------------------------------------------------------
User feedback Some timing activities are opened early or postponed
1) Log in to the server, check the time is really slow or fast. In short, there are several server time is inaccurate.
2) View the code that is used by the Scheduledexecutorservice. scheduleatfixedrate, Java API, so there's no bug here.
3) View log4j log output discovery:
12-point timing activity, the previous [activity run time] is 12 o'clock, and a few days after the [activity run time] is 12 points 0 minutes, and seconds are consistent
Confirm that the changes have synchronized the server time, but the JVM has not been restarted
4) initial suspicion is that scheduledexecutorservice internal execution uses a relative time, not every sampling server system time

Issue confirmation-Test:
--------------------------------------------------------------------------------
5) Testing

Scheduledexecutorservice service = Executors.newscheduledthreadpool (2); Service.scheduleatfixedrate (NewRunnable () {//Runnable-1@Override Public voidrun () {System.out.println (String.Format (' \n####%s # # # # # #,                 NewSimpleDateFormat ("Yyyy-mm-dd HH:mm:ss. S "). Format (NewDate ()))); }}, 0, ten, timeunit.seconds);//10 seconds to execute onceService.scheduleatfixedrate (NewRunnable () {//Runnable-2inti = 0; @Override Public voidrun () {System.out.print ((i++) + "," ); }}, 0, 1, timeunit.seconds);//1 seconds to execute once

Output-1:
    0,
    #### 2014-11-28 16:51:48.118 # # # #
     1,2,3,4,5,6,7,8,9,
    #### 2014-11-28 16:51:58.93 # # # # #
     10,11,12,13,14,15,16,17,18,19,20,
    #### 2014-11-28 16:52:08.94 # # # # #
     21,22,23,24,25,26,27,28,29,
    #### 2014-11-28 16:52:18.93 # # #
    30,31,32,33,34,35,36,37,38,39,
    #### 2014-11-28 16:52:28.93 # # # #
    40,41,42,43,44,45,46,47,48,49,
    #### 2014-11-28 16:58:36.480 #//Adjustment time
    50,51,52,53,54,55,56,57,58,59,
    #### 2014-11-28 strong>16:58:46.480
# # # #
    60,61,62,63,64,65,66,67,68,69,
    #### 2014-11-28 16:58:56.480 # # # #

When the 16:52:28.93 time is 16:58:36.480 (backward), Runnable-2 still outputs 10 times and Runnable-1 output 1 times

Output-2:
0,
# # # 2014-11-28 17:12:40.971 # # #
1,2,3,4,5,6,7,8,9,
# # # # 2014-11-28 17:12:50.943 # #
10,11,12,13,14,15,16,17,18,19,
# # # # 2014-11-28 17:13:00.943 # # #/Adjust Time
20,21,22,23,24,25,26,27,28,29,
# # # # 2014-11-28 17:05:09.69 # #
30,31,32,33,34,35,36,37,38,39,
# # # # 2014-11-28 17:05:19.68 # #

When the 17:13:00.943 time is 17:05:09.69 (forward hop), the Runnable-2 still outputs 10 times and then Runnable-1 output 1 times

Test conclusion: Time jumps do not affect Runnable-1 10 seconds unit output once, Scheduledexecutorservice not using system time

Issue Confirmation-JDK Source:
--------------------------------------------------------------------------------
Initialization

Scheduledexecutorservice service = Executors.newscheduledthreadpool (2);     New scheduledthreadpoolexecutor (corepoolsize)         Super New Delayedworkqueue ())

Registering timed Tasks

Service.scheduleatfixedrate (NewRunnable () {...}) Runnablescheduledfuture<?> t = decoratetask (command,NewScheduledfuturetask<object> (Command,NULL, Triggertime (initialdelay, Unit), Unit.tonanos (period)); //Scheduledthreadpoolexecutor.scheduledfuturetaskDelayedexecute (t); Prestartcorethread addifundercorepoolsize addthread Worker w=NewWorker (Firsttask);//Threadpoolexecutor.workerThread T =Threadfactory.newthread (W);        Workers.add (w); Super. Getqueue (). Add (command);//Delayedworkqueue

Perform

ThreadPoolExecutor.Worker.run     = Gettask ()        = Workqueue.take ();       // Delayedworkqueue ScheduledThreadPoolExecutor.DelayedWorkQueue.take    dq.take ();          // delayqueue<runnablescheduledfuture>
 delayqueue<e extends Delayed> 
an unbounded blocking queue of Delayed elements that can be extracted from an element only when the delay expires. The head of the queue is the Delayed element with the longest save time after the delay expires. If the delay has not expired, the queue does not have a header, and poll returns null . When an element's Getdelay (Timeunit.nanoseconds) method returns a value that is less than or equal to 0 null element. Take () long delay = First.getdelay (Timeu Nit. nanoseconds); if (Delay > 0) { long tl = Available.awaitnanos (delay); }
ScheduledThreadPoolExecutor.ScheduledFutureTask.getDelay  
Public Long getdelay (timeunit unit) { return Unit.convert (Time-now (), timeunit.nanoseconds); } finallong now () { /** * public static long Nanotime ( * Returns the current value of the most accurate available system timer, measured in nanoseconds. * This method can only be used to measure the time that has been spent, regardless of any other time concept of the system or clock time. * The return value indicates the number of nanoseconds from a fixed but arbitrary time (perhaps from a later date, so the value may be negative). */ return System.nanotime ()- nano_origin; }

Issue Confirmation-nanotime Test:
--------------------------------------------------------------------------------

NewThread () { Public voidrun () {LongLastnanos =System.nanotime (); LongLastmilis =System.currenttimemillis ();  for(inti = 0; I < 100; i++) {            Try{Thread.Sleep (10000L);}Catch(Interruptedexception e) { }//output once in 10 seconds                        LongNanos =System.nanotime (); LongMillis =System.currenttimemillis (); System.out.println (String.Format ("%-25s%-10s%s-%s =%s [%s]",                    NewSimpleDateFormat ("Yyyy-mm-dd HH:mm:ss. S "). Format (NewDate (Millis)), Millis-Lastmilis, Nanos, Lastnanos, Nanos-Lastnanos, (Nanos-lastnanos)/1000/1000            )); Lastnanos=Nanos; Lastmilis=Millis; }}}.start ();

Output:
2014-12-05 10:10:45.950 10001 107273041687944-107263041775958 = 9999911986 [9999]
2014-12-05 10:10:55.997 10047 107283088127723-107273041687944 = 10046439779 [10046]
2014-12-05 10:20:04.198 548201 107293088578057-107283088127723 = 10000450334 [10000]
2014-12-05 10:00:12.399 -1191799 107303089035855-107293088578057 = 10000457798 [10000]
2014-12-05 10:00:22.399 10000 107313089495208-107303089035855 = 10000459353 [10000]
Adjust the time to 10:20:04.198 (jump backwards) when 10:10:55.997, and adjust the time to 10:00:12.399 (forward jump) at 10:20:04.198
Nanos-lastnanos is always maintained at around 10s, Millis-lastmilis does expect the time

Ideas and Goals:
--------------------------------------------------------------------------------
7) I want to make a timer that relies on the timer of the current system time, and by the way solves the current problem
A) It is not a scheduled task, not a task system.
b) It only does one thing, it's time to remind me to do a task.
For example, 12 points, remind me to eat the flower chicken, 20, it's time to fight the battle.

Preliminary design:
--------------------------------------------------------------------------------

8) Preliminary design
A) First create a task thread pool to perform the task of waking up the timer.
Executors.newscheduledthreadpool (Workservicepoolsize)
b) Create a timer thread that executes handlefunc once every 1 seconds (heartbeat step 1 seconds)
Executors.newsinglethreadscheduledexecutor
c) Handlefunc the task to the task thread pool, based on the current system time to find the task.
Execute (new Runnable () {});
Can initially resolve the task depends on the system time to execute the problem

Detailed design:
--------------------------------------------------------------------------------

9) Linux system time will be faster or slower, such as the 23-point battle Force leaderboard and after 30 minutes to start collecting rewards
A) If the speed is too much, everyone is 22:55, but the server has 23:00, want to wait for the final punch of the brothers immediately cried
b) If it's too slow, everyone is 23:00, but the server is 22:55, I'm all rested, ready to start collecting rewards, and you can hit the list of forces.

A) Handlefunc after each execution, record the current execution time as Lastexecutetime
b) Handlefunc the next execution, take executetime (current time) and Lastexecutetime compare
if Executetime = = Lastexecutetime + 1: (Heartbeat step 1 seconds)
Normal time, normal execution
If executetime > lastexecutetime + 1:
Time is running out (usually server time is slow; correct server time, server time is fast forward), need to handle:
[Lastexecutetime + 1, executeTime-1] The task depends on the business decision whether to immediately fill the execution
[Executetime] Task is the current time normal task, need to execute normally
If Executetime <= lastexecutetime:
The time is slow (usually the server time is fast; the server time is corrected and the server time is rolled back):
[Executetime, Lastexecutetime] have been executed, generally do not need to carry out

Note 1: The current time and lastexecutetime are all erased milliseconds, and the daily timer service is calculated based on the seconds.
NOTE 2: The server can synchronize time every 1 hours, for example, nn:38, usually avoid the whole point, the slightest, the entire
Note 3: Synchronization of the maximum error for a few seconds per hour, for ordinary business:
When the time is fast, you can do it immediately, and the more important reward is not much different in advance or 5 seconds delay.
In the case of slow time, you can ignore the [Executetime, Lastexecutetime] task, do not need to execute again
Note 4: The execution time granularity is smaller, say 1 seconds to execute once, can ignore the time jumps the question

Detailed design-timed tasks:
--------------------------------------------------------------------------------

10) It is possible to solve the problem of time jumping by using the timer scheme, but the daily development is usually a scheduled cycle task.
For example, 12 o ' clock eat called Flower chicken, 12 o ' clock timer notice eat called flower chicken, but eat the chicken is 12 o ' clock every day to eat, this is a regular cycle task, need 12 points per day
Tell me to eat. The processing scheme can be as follows:
A) Modify the task that Handlefunc finds when it is based on the current system time
b) Find a task warehouse divided into two types of warehouses:
Disposable Task Warehouse:
Execute the task and remove it in time; The storage key for the task warehouse is the task execution timestamp
Daily Task Warehouse:
The storage key for the task warehouse is the number of seconds that the task is relative to 00:00:00
Handlefunc execution time, look at how many seconds past today (this is using system time), find the corresponding task, and then execute. This does not require removal of the task

This is still the concept of the timer, "12 o ' clock to the time, I told you to eat a flower chicken; tomorrow at 12 o ' clock, I'll ask you to eat chicken with flowers .
Instead of "12, I told you to eat chicken, and 24 hours later I'll ask you to eat chicken."

Note 1: The same can be added weekly, hourly, per minute task warehouses
Note 2: Usually do not need monthly, yearly, every ten years, such as cycle tasks, if need to add also very simple
Note 3: Every second, do not need so many things, handlefunc after the direct execution (each time interval is calculated using the Nano 1 seconds, so should be executed)

Interface design:
--------------------------------------------------------------------------------

11) External interface:
A) Start
b) Close
c) Register a one-time mission
d) Registration of weekly missions
e) Registration of daily tasks
f) Register each time task: What tasks are performed in the first and second of each hour
g) Registration of each sub-mission
h) Register per second task

Other instructions:
--------------------------------------------------------------------------------

12) Other:
A) Handlefunc just find the task to throw it into the worker pool execution, not CPU-intensive, does not cause the task to pick up the blockage
b) Handlefunc each time will go to the minutes of the task warehouse to find the appropriate task and execute; the same task did not play on the last minute, the current task will continue to execute, no delay, will be executed at the same time
Since it is a per-minute task, the task should not exceed 1 minutes, and if it is occasionally more than 1 minutes, you can lock yourself in the registered task.
c) The server time is slow, the server time is adjusted, the server time is fast forward, and the execution task only takes a certain amount of time (for example, 30 minutes).
The system time is 1 hours synchronization once, the error is only a few seconds, if again big, should upgrade the kernel or change the server
The time period during which the execution is performed may affect normal service (normal service process, system resource consumption, etc.)
d) When the task is thrown into the thread pool, it will be caught in an extra catch to prevent the current thread from being hung out

"Original" Timer and system time

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.