In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article will explain in detail how the ScheduledExecutorService implementation of timing tasks is, and the content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.
Now it is almost impossible for a project to define a ScheduledExecutorService to perform scheduled tasks. Third-party frameworks such as xxl-job are used, but it is necessary to understand the most basic principles of scheduled tasks.
Simple example of ScheduledExecutorService
Let's first look at the simplest use, as shown in the following figure:
ScheduledThreadPoolExecutor is the implementation of ScheduledExecutorService, which can do some basic timing tasks.
For example, in the example above, you can delay the execution of a task every 5 seconds after a delay of 3 seconds. It's easy to implement.
Basic source code analysis
First of all, ScheduledThreadPoolExecutor inherits ThreadPoolExecutor and implements ScheduledExecutorService, so it has the function of thread pool.
Then we look at its construction method, it has several construction methods, let's take the example above, there is only one line of code in the method:
Super (corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue ())
The constructor of the parent class, that is, the constructor of the thread pool, is called, which does not implement the task itself, except that new gives a DelayedWorkQueue () to the parent class, which stores the task queue for the thread pool.
Submit task method source code
ScheduledThreadPoolExecutor provides several ways to perform scheduled tasks, but let's analyze the scheduleAtFixedRate method used above and see the source code as shown below:
There are only three steps in this method:
First initialize ScheduledFutureTask, which inherits FutureTask and extends some attributes needed for scheduled tasks, such as the next execution time and the interval between each task.
Then call the decorateTask method to decorate the task, currently there is no task to do, we can customize to implement some functions.
Finally, call the delayedExecute method, from the figure above, you can see that the main process of this method is also simple. First, put the task in the queue of the thread pool, and then call the ensurePrestart method. The ensurePrestart method is the method of the thread pool, and the function is to call the addWorker method according to the number of threads in the thread pool. The addWorker method is not much to say. Students who are not clear can see my previous articles "three minutes to understand the thread pool execution process".
The method of submitting a scheduled task is simple, wrapping a task (used to hold the information needed by the timed task) and then submitting it to the queue of the thread pool.
But there is a problem is that the task is submitted to the thread pool, we know that the thread pool can execute the task, but it is executed once, not like a scheduled task! So how on earth does it achieve the function of timing tasks?
The key first step to realize the timing task
From the previous article, it is analyzed that the final execution in the thread pool is the run method of the submitted task, so ScheduledFutureTask has a special implementation of the run method. There are two steps to follow the process of following the source code to find that the run method is normal:
Call ScheduledFutureTask.super.runAndReset (), that is, call the runAndReset () method of the parent class's FutureTask. This method is not mentioned in the previous article, that is, call the run of the internal Callable to save the result.
After the last execution, that is, the task is completed, setNextRunTime (); reExecutePeriodic (outerTask); two-step code is called. The first step is to calculate the execution time of the next task, and the second is to put the task in the queue.
The run method executes the specific method, recalculates the next execution time of the task after the successful execution of the task, and loads the task into the queue again for repeated execution.
But so far, it has only been implemented to specify when to execute and repeat execution, so how on earth is it implemented at a specific time?
Delay queue to realize timing execution
Still did not find how to achieve timed execution, there is no way to continue to follow the code, and finally follow the thread pool runWorker method, in getting the firstTask method of Worker to execute, remember that just in the call ensurePrestart method called addWorker method to pass the firstTask is null, that is to say, Worker tasks are pulled from the queue of tasks, they do not have their own firstTask.
It is also remembered that the queue passed to the thread pool by the initialization method is new DelayedWorkQueue (); so we should basically find the problem, let's take a look at the queue's take method:
You can see from the source code that it is based on the first element in the queue, and then uses the getDelay method of ScheduledFutureTask to determine whether the task is returned or blocked. GetDelay subtracts the current time according to the attribute time (the next task execution time mentioned earlier).
So if the first task is judged to be executed after 10 seconds, and the second task is judged to be executed after 5 seconds, does the second task wait until the first task is finished?
Obviously you can't do that, so let's take a look at DelayedWorkQueue's add method, which doesn't implement the add method, but the offer,DelayedWorkQueue called by the add method implements the offer method.
The offer method is also simple, that is, add the task to the queue array, add it directly if the array is null, and wake up the thread where the take is. If it is not null, compare the time of the task in the array. The closer the task is, the earlier it is. If the newly added task is set to the first one in the array, wake up the thread blocked by take.
ScheduledExecutorService inherits the thread pool and also submits the task to the thread pool for execution, but its task class is extended.
The task class ScheduledFutureTask inherits FutureTask and extends some properties to record the next execution time and interval of each execution of the task. At the same time, the run method is overridden to recalculate the next execution time of the task and put the task in the thread pool queue.
ScheduledExecutorService customizes the blocking queue DelayedWorkQueue for thread pool use, it can block the take method according to the next execution time of the ScheduledFutureTask, and the new ScheduledFutureTask will be sorted according to this time, the smallest first.
To sum up, tasks are executed through thread pool, ScheduledFutureTask records task timing information, and DelayedWorkQueue sorts task timing execution.
On the timing task ScheduledExecutorService implementation is how to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.