In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "three implementation methods of java timing tasks". In daily operation, I believe that many people have doubts about the three implementation methods of java timing tasks. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "three implementation methods of java timing tasks". Next, please follow the editor to study!
TOP 1:Timer
Timer is a scheduled task execution class that comes with JDK. Any project can directly use Timer to implement scheduled tasks, so the advantage of Timer is that it is easy to use. Its implementation code is as follows:
Public class MyTimerTask {
Public static void main (String [] args) {
/ / define a task
TimerTask timerTask = new TimerTask () {
@ Override
Public void run () {
System.out.println ("Run timerTask:" + new Date ())
}
}
/ / timer
Timer timer = new Timer ()
/ / add execution tasks (delayed execution for 1 second, once every 3 seconds)
Timer.schedule (timerTask, 1000, 3000)
}
}
The execution result of the program is as follows:
Run timerTask:Mon Aug 17 21:29:25 CST 2020
Run timerTask:Mon Aug 17 21:29:28 CST 2020
Run timerTask:Mon Aug 17 21:29:31 CST 2020
Analysis of shortcomings of Timer
Although it is convenient to implement scheduled tasks, the Timer class needs to pay attention to the following problems when using it.
Problem 1: long task execution time affects other tasks
When the execution time of one task is too long, it will affect the scheduling of other tasks, as shown in the following code:
Public class MyTimerTask {
Public static void main (String [] args) {
/ / define Task 1
TimerTask timerTask = new TimerTask () {
@ Override
Public void run () {
System.out.println ("enter timerTask 1:" + new Date ())
Try {
/ / dormant for 5 seconds
TimeUnit.SECONDS.sleep (5)
} catch (InterruptedException e) {
E.printStackTrace ()
}
System.out.println ("Run timerTask 1:" + new Date ())
}
}
/ / define Task 2
TimerTask timerTask2 = new TimerTask () {
@ Override
Public void run () {
System.out.println ("Run timerTask 2:" + new Date ())
}
}
/ / timer
Timer timer = new Timer ()
/ / add execution tasks (delayed execution for 1 second, once every 3 seconds)
Timer.schedule (timerTask, 1000, 3000)
Timer.schedule (timerTask2, 1000, 3000)
}
}
The execution result of the program is as follows:
Enter timerTask 1:Mon Aug 17 21:44:08 CST 2020
Run timerTask 1:Mon Aug 17 21:44:13 CST 2020
Run timerTask 2:Mon Aug 17 21:44:13 CST 2020
Enter timerTask 1:Mon Aug 17 21:44:13 CST 2020
Run timerTask 1:Mon Aug 17 21:44:18 CST 2020
Enter timerTask 1:Mon Aug 17 21:44:18 CST 2020
Run timerTask 1:Mon Aug 17 21:44:23 CST 2020
Run timerTask 2:Mon Aug 17 21:44:23 CST 2020
Enter timerTask 1:Mon Aug 17 21:44:23 CST 2020
As can be seen from the above results, when the running time of Task 1 exceeds the set interval, Task 2 will also delay execution. The original execution interval of Task 1 and Task 2 was 3 seconds, but because Task 1 was executed for 5 seconds, the execution interval of Task 2 became 10 seconds (which did not match the original time).
Question 2: task exceptions affect other tasks
When a scheduled task is implemented using the Timer class, when one task throws an exception, the other tasks are also terminated, as shown in the following code:
Public class MyTimerTask {
Public static void main (String [] args) {
/ / define Task 1
TimerTask timerTask = new TimerTask () {
@ Override
Public void run () {
System.out.println ("enter timerTask 1:" + new Date ())
/ / simulated exception
Int num = 8 / 0
System.out.println ("Run timerTask 1:" + new Date ())
}
}
/ / define Task 2
TimerTask timerTask2 = new TimerTask () {
@ Override
Public void run () {
System.out.println ("Run timerTask 2:" + new Date ())
}
}
/ / timer
Timer timer = new Timer ()
/ / add execution tasks (delayed execution for 1 second, once every 3 seconds)
Timer.schedule (timerTask, 1000, 3000)
Timer.schedule (timerTask2, 1000, 3000)
}
}
The execution result of the program is as follows:
Enter timerTask 1:Mon Aug 17 22:02:37 CST 2020
Exception in thread "Timer-0" java.lang.ArithmeticException: / by zero
At com.example.MyTimerTask$1.run (MyTimerTask.java:21)
At java.util.TimerThread.mainLoop (Timer.java:555)
At java.util.TimerThread.run (Timer.java:505)
Process finished with exit code 0
Summary of Timer
The advantage of Timer class to implement scheduled tasks is convenient, because it is a scheduled task defined by JDK, but the disadvantage is that if the task execution time is too long or the task execution is abnormal, it will affect the scheduling of other tasks, so it is recommended to use it cautiously in production environment.
TOP 2:ScheduledExecutorService
ScheduledExecutorService is also the API that comes with JDK 1.5, and we can use it to implement the function of scheduled tasks, that is to say, ScheduledExecutorService can achieve all the functions of Timer class, and it can solve all the problems of Timer class.
An example of the code for ScheduledExecutorService to implement a scheduled task is as follows:
Public class MyScheduledExecutorService {
Public static void main (String [] args) {
/ / create a task queue
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool (10); / / 10 is the number of threads
/ / perform the task
ScheduledExecutorService.scheduleAtFixedRate (()-> {
System.out.println ("Run Schedule:" + new Date ())
}, 1, 3, TimeUnit.SECONDS); / / starts execution after 1 s, and executes every 3 s
}
}
The execution result of the program is as follows:
Run Schedule:Mon Aug 17 21:44:23 CST 2020
Run Schedule:Mon Aug 17 21:44:26 CST 2020
Run Schedule:Mon Aug 17 21:44:29 CST 2020
ScheduledExecutorService Reliability Test ① task timeout execution test
ScheduledExecutorService can solve the disadvantage of the corresponding influence between Timer tasks. First, let's test whether the long execution time of one task will affect other tasks. The test code is as follows:
Public class MyScheduledExecutorService {
Public static void main (String [] args) {
/ / create a task queue
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool (10)
/ / execute Task 1
ScheduledExecutorService.scheduleAtFixedRate (()-> {
System.out.println ("enter Schedule:" + new Date ())
Try {
/ / dormant for 5 seconds
TimeUnit.SECONDS.sleep (5)
} catch (InterruptedException e) {
E.printStackTrace ()
}
System.out.println ("Run Schedule:" + new Date ())
}, 1, 3, TimeUnit.SECONDS); / / starts execution after 1 s, and executes every 3 s
/ / execute Task 2
ScheduledExecutorService.scheduleAtFixedRate (()-> {
System.out.println ("Run Schedule2:" + new Date ())
}, 1, 3, TimeUnit.SECONDS); / / starts execution after 1 s, and executes every 3 s
}
}
The execution result of the program is as follows:
Run Schedule2:Mon Aug 17 11:27:55 CST 2020
Enter Schedule:Mon Aug 17 11:27:55 CST 2020
Run Schedule2:Mon Aug 17 11:27:58 CST 2020
Run Schedule:Mon Aug 17 11:28:00 CST 2020
Enter Schedule:Mon Aug 17 11:28:00 CST 2020
Run Schedule2:Mon Aug 17 11:28:01 CST 2020
Run Schedule2:Mon Aug 17 11:28:04 CST 2020
From the above results, it can be seen that when the execution time of task 1 exceeds the execution frequency of 3s, it does not affect the normal execution of task 2, so using ScheduledExecutorService can avoid the impact of too long task execution time on other tasks.
② task exception test
Next, let's test whether ScheduledExecutorService will affect other tasks when one task is abnormal. The test code is as follows:
Public class MyScheduledExecutorService {
Public static void main (String [] args) {
/ / create a task queue
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool (10)
/ / execute Task 1
ScheduledExecutorService.scheduleAtFixedRate (()-> {
System.out.println ("enter Schedule:" + new Date ())
/ / simulated exception
Int num = 8 / 0
System.out.println ("Run Schedule:" + new Date ())
}, 1, 3, TimeUnit.SECONDS); / / starts execution after 1 s, and executes every 3 s
/ / execute Task 2
ScheduledExecutorService.scheduleAtFixedRate (()-> {
System.out.println ("Run Schedule2:" + new Date ())
}, 1, 3, TimeUnit.SECONDS); / / starts execution after 1 s, and executes every 3 s
}
}
The execution result of the program is as follows:
Enter Schedule:Mon Aug 17 22:17:37 CST 2020
Run Schedule2:Mon Aug 17 22:17:37 CST 2020
Run Schedule2:Mon Aug 17 22:17:40 CST 2020
Run Schedule2:Mon Aug 17 22:17:43 CST 2020
As can be seen from the above results, when an exception occurs in Task 1, it will not affect the execution of Task 2.
Summary of ScheduledExecutorService
It is recommended to use ScheduledExecutorService to perform scheduled tasks in a stand-alone production environment. It is the API that comes with JDK 1.5, so it is easy to use, and using ScheduledExecutorService to execute tasks will not cause mutual influence between tasks.
TOP 3:Spring Task
If you are using Spring or Spring Boot framework, you can directly use the scheduled tasks that come with Spring Framework. Using the above two implementation methods of scheduled tasks, it is difficult to achieve scheduled tasks with a specific time, for example, when we need to execute a task every Friday, but if we use Spring Task, we can easily achieve this requirement.
Taking Spring Boot as an example, it takes only two steps to implement a scheduled task:
Open timed tasks; add scheduled tasks.
The specific implementation steps are as follows.
① starts timing task
You only need to declare @ EnableScheduling on the startup class of Spring Boot to enable the timing task. The implementation code is as follows:
@ SpringBootApplication
@ EnableScheduling / / start timing task
Public class DemoApplication {
/ / do someing
}
② add scheduled tasks
You only need to use @ Scheduled annotation to add scheduled tasks. If you have multiple scheduled tasks, you can create multiple @ Scheduled annotation methods. The sample code is as follows:
Import org.springframework.scheduling.annotation.Scheduled
Import org.springframework.stereotype.Component
@ Component / / this class is hosted to Spring and cannot be omitted
Public class TaskUtils {
/ / add scheduled tasks
@ Scheduled (cron = "59 59 23 0 05") / / cron expression, executed every Friday at 23:59:59
Public void doTask () {
System.out.println ("I am a timed task ~")
}
}
Note: scheduled tasks are triggered automatically without manual intervention, which means that scheduled tasks are loaded and executed automatically after Spring Boot starts.
Cron expression
The implementation of Spring Task requires the use of cron expressions to declare the frequency and rules of execution. Cron expressions are composed of 6 or 7 bits (the last bit can be omitted), separated by spaces, and each represents the following meaning from left to right:
Among them * and? Number indicates that it matches all the time.
Cron expression generated online address: https://cron.qqe2.com/
Knowledge extension: distributed timing tasks
The above methods are all about the implementation of timing tasks on a single machine. If it is a distributed environment, you can use Redis to achieve timing tasks.
The methods of implementing deferred tasks using Redis can be divided into two categories: the way of ZSet and the way of keyspace notification.
① ZSet implementation
The idea of implementing scheduled tasks through ZSet is to store scheduled tasks in the ZSet collection, and store the expiration time in the Score field of ZSet, and then determine whether there are scheduled tasks that need to be executed within the current time through a wireless loop. If so, execute them. The specific implementation code is as follows:
Import redis.clients.jedis.Jedis
Import utils.JedisUtils
Import java.time.Instant
Import java.util.Set
Public class DelayQueueExample {
/ / zset key
Private static final String _ KEY = "myTaskQueue"
Public static void main (String [] args) throws InterruptedException {
Jedis jedis = JedisUtils.getJedis ()
/ / execute after 30s
Long delayTime = Instant.now (). PlusSeconds (30). GetEpochSecond ()
Jedis.zadd (_ KEY, delayTime, "order_1")
/ / continue to add test data
Jedis.zadd (_ KEY, Instant.now (). PlusSeconds (2). GetEpochSecond (), "order_2")
Jedis.zadd (_ KEY, Instant.now (). PlusSeconds (2). GetEpochSecond (), "order_3")
Jedis.zadd (_ KEY, Instant.now (). PlusSeconds (7). GetEpochSecond (), "order_4")
Jedis.zadd (_ KEY, Instant.now (). PlusSeconds (10). GetEpochSecond (), "order_5")
/ / Open timed task queue
DoDelayQueue (jedis)
}
/ * *
* timed task queue consumption
* @ param jedis Redis client
, /
Public static void doDelayQueue (Jedis jedis) throws InterruptedException {
While (true) {
/ / current time
Instant nowInstant = Instant.now ()
Long lastSecond = nowInstant.plusSeconds (- 1) .getEpochSecond (); / / time in the previous second
Long nowSecond = nowInstant.getEpochSecond ()
/ / query all tasks at the current time
Set data = jedis.zrangeByScore (_ KEY, lastSecond, nowSecond)
For (String item: data) {
/ / consumption tasks
System.out.println ("consumption:" + item)
}
/ / Delete tasks that have been performed
Jedis.zremrangeByScore (_ KEY, lastSecond, nowSecond)
Thread.sleep (1000); / / query once per second
}
}
}
② key space notification
We can realize the scheduled task through the keyspace notification of Redis. The idea of its implementation is to set an expiration time for all scheduled tasks. After the expiration, we can sense that the scheduled task needs to be executed by subscribing to the expiration message, and then we can execute the scheduled task.
By default, Redis does not enable keyspace notification. You need to enable it manually through the command of config set notify-keyspace-events Ex. The code for scheduled tasks after enabling is as follows:
Import redis.clients.jedis.Jedis
Import redis.clients.jedis.JedisPubSub
Import utils.JedisUtils
Public class TaskExample {
Public static final String _ TOPIC = "_ _ keyevent@0__:expired"; / / subscription channel name
Public static void main (String [] args) {
Jedis jedis = JedisUtils.getJedis ()
/ / perform scheduled tasks
DoTask (jedis)
}
/ * *
* subscribe to expired messages and perform scheduled tasks
* @ param jedis Redis client
, /
Public static void doTask (Jedis jedis) {
/ / subscribe to expired messages
Jedis.psubscribe (new JedisPubSub () {
@ Override
Public void onPMessage (String pattern, String channel, String message) {
/ / receive the message and execute the scheduled task
System.out.println ("received message:" + message)
}
}, _ TOPIC)
}
}
At this point, the study of "three implementation methods of java timing tasks" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
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.