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

Three implementation methods of java timing Task

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.

Share To

Internet Technology

Wechat

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

12
Report