There are several ways to implement a scheduled task:

Timer: This is the java.util.Timer class that comes with Java. This class allows you to schedule a java.util.TimerTask. This allows your program to run at a certain frequency, but not at a specified time. Generally used less.

ScheduledExecutorService: also a JDK class; Is a scheduled task class based on thread pool design, each scheduled task will be assigned to a thread in the thread pool to execute, that is, the task is concurrent execution, do not affect each other.

Spring Task: The Task that comes with Spring3.0 can be thought of as a lightweight Quartz and is much simpler to use.

Quartz: This is a powerful scheduler that allows your program to execute at a specified time or at a certain frequency. Configuration is a bit complicated.

Use the Timer

This is currently used less in the project, directly paste demo code. See the API for details

public class TestTimer {

   public static void main(String[] args) {

       TimerTask timerTask = new TimerTask() {
           @Override
           public void run() {
               System.out.println("task run:"+ new Date()); }}; Timer timer = new Timer(); // Schedule the specified task to start repeated fixed delay execution at the specified time. Here timer.schedule(timerTask,10,3000) is executed every 3 seconds; }}Copy the code

Using ScheduledExecutorService

This method is similar to Timer.

public class TestScheduledExecutorService { public static void main(String[] args) { ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); / / parameters: 1, task 2, performed for the first time delay / / 3, task execution time interval of 4, time interval unit service. ScheduleAtFixedRate (() - > System. Out. Println ("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS); }}Copy the code

Using the Spring Task

Simple scheduled tasks

In the SpringBoot project, we can elegantly use annotations to implement timed tasks by first creating the project and importing dependencies:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>  </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional>
 </dependency>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
 </dependency>

</dependencies>
Copy the code

Create task class:

@Slf4j

@Component

public class ScheduledService {

   @Scheduled(cron = "0/5 * * * * *")
   public void scheduled(){
       log.info("=====>>>>> using cron {}",System.currentTimeMillis());
   }

   @Scheduled(fixedRate = 5000)
   public void scheduled1() {
       log.info("= = = = = > > > > > use fixedRate {}", System.currentTimeMillis());
   }

   @Scheduled(fixedDelay = 5000)
   public void scheduled2() {
       log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis()); }}Copy the code

Turn on support for scheduled tasks with the @enablesCheduling annotation on the main class, and then start the project

Recommended: Spring Quick start plan. If there is only one scheduled task, this is not a problem. If the number of scheduled tasks increases, if one task is blocked, other tasks cannot be executed.

Multithreaded execution

In a traditional Spring project, we can add the configuration of task to the XML configuration file, whereas in a SpringBoot project, we usually add the configuration using the config configuration class, so create a new AsyncConfig class. Follow the wechat official account of Java technology stack and reply the keyword: Spring in the background to get more dry products of Spring series of technology with stack length sorted

@configuration @enableAsync Public class AsyncConfig {/* * where member variables should be read from the Configuration using @value */ private int corePoolSize = 10; private int maxPoolSize = 200; private int queueCapacity = 10; @Bean public ExecutortaskExecutor() {
       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       executor.setCorePoolSize(corePoolSize);
       executor.setMaxPoolSize(maxPoolSize);
       executor.setQueueCapacity(queueCapacity);
       executor.initialize();
       returnexecutor; }}Copy the code

@configuration: indicates that the class is a Configuration class

@enableAsync: Enable asynchronous event support

Then add @async to the class or method of the scheduled task. Finally, restart the project, with each task in a different thread.

Configure the execution time

In the Scheduled task above, we used the @scheduled annotation on the method to set the execution time of the task and used three properties configuration methods:

FixedRate: Defines a scheduled task that executes at a certain frequency

FixedDelay: Defines a scheduled task to be executed at a certain frequency. Different from the above, the modified attribute can be used with initialDelay to define the execution time of the task.

Cron: Uses an expression to set the execution time of a task

Cron expression details

A CRon expression has at least six (and possibly seven) space-separated time elements. In order:

59 seconds (0 ~)

Minutes (0~59)

Hours (0~23)

Days (0 ~ 31)

Month (0 ~ 11)

Week (1 to 7 1=SUN or SUN, MON, TUE, WED, THU, FRI, SAT)

Year (1970-2099)

Each element can be a value (e.g., 6), a contiguous interval (9-12), an interval (8-18/4)(/ means every 4 hours), a list (1,3,5), and a wildcard. Because the date of the month and date of the week elements are mutually exclusive, you must set one of them.

Configuration examples:

This command is executed every 5 seconds: /5 *?

Run this command every minute: 0/1?

0 0 10,14,16? Every day at 10 a.m., 2 p.m., 4 p.m

0 0/30 9-17? Every half hour during your 9-5 working hours

0 0 12? * WED means every Wednesday at 12 noon

“0 0 12?” It’s triggered every day at 12 noon

“0 15 10? “It’s triggered every day at 10:15 a.m

“0 15 10?” Triggered every day at 10:15 a.m

“0 15 10? * “triggered every day at 10:15 a.m

“0 15 10? 2005 “triggered at 10:15 a.m. every day in 2005

“0 to 14 *?” Triggered every minute between 2 p.m. and 2:59 p.m. each day

14 “0 0/5?” Triggered every 5 minutes between 2 p.m. and 2:55 p.m. each day

“0/5 0 14, 19?” Triggered every 5 minutes between 2 p.m. and 2:55 p.m. and 6 p.m. and 6:55 p.m. each day

“0 0 to 5 14?” Triggered every minute between 2 p.m. and 2:05 p.m. each day

“0 10 44 14? 3 WED is triggered at 2:10 PM and 2:44 PM on Wednesdays in March each year

“0 15 10? * Mon-FRI triggers Monday through Friday at 10:15 a.m

“0 15 10 15 *?” Triggered at 10:15 am on the 15th of each month

“0, 15, 10 L *? Triggered at 10:15 a.m. on the last day of each month

“0 15 10? * 6L “triggers at 10:15 am on the last Friday of each month

“0 15 10? * 6L 2002-2005 “triggered on the last Friday of each month from 2002 to 2005 at 10:15 am

“0 15 10? * 6#3 “triggers at 10:15 am on the third Friday of each month

Some subexpressions can contain ranges or lists

For example, the subexpression (day (week)) can be “mon-fri”, “MON, WED, FRI”, “mon-wed,SAT”. The “*” character represents all possible values and the “/” character is used to specify the increment of the value

For example, “0/15” in the subexpression (minutes) means the beginning of minute 0, and “3/20” in the subexpression (minutes) means the beginning of minute 3, and every 20 minutes (which has the same meaning as “3, 23, 43”) means “?” The day (month) and day (week) subexpressions are used only, indicating that no value is specified. When one of the two subexpressions is specified, the value of the other subexpression is set to? To avoid conflicts.

The “L” character is used only in day (month) and day (week) subexpressions. It is a contraction of the word “last”. If there is something concrete before the “L”, it has another meaning.

For example: “6L” indicates the sixth to last day of the month note: Do not specify a list or range when using the “L” argument, as this can cause problems. The W character stands for weekdays (mon-FRi) and can only be used in the day field. It is used to specify the nearest weekday to a specified day. Most business processes are workweek-based, so the W character can be very important.

For example, 15W in the daily domain means “the nearest weekday to the 15th of the month.” If the 15th falls on a Saturday, the trigger will be triggered on Friday the 14th because Thursday is closer to the 15th than Monday. C: Calendar. It means the date to which the plan is associated, or if the date is not associated, all dates in the calendar.

For example 5C in the date field corresponds to the first day after the 5th day of the calendar. 1C in the week field corresponds to the day after Sunday.

Integration of Quartz

Add the dependent

Spring-boot-starter: spring-boot-starter: quart-quartz: spring-boot-starter: Quart-starter: Quart-starter: Quart-starter: Quart-starter: quart-starter: quart-starter: quart-starter: quart-starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Copy the code

If 1.5.9, add dependencies using the following:

< the dependency > < groupId > org. Quartz - the scheduler < / groupId > < artifactId > quartz < / artifactId > < version > 2.3.0 < / version > </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency>Copy the code

The SpringBoot version I’m using here is 2.0.0. build-snapshot, which starts with Quartz integration, so it’s easy to implement. Others seem to be more troublesome, so I will not introduce them here. Later, I will have time to learn more about Quartz in detail.

Create the task class TestQuartz, which inherits QuartzJobBean

Public class TestQuartz extends QuartzJobBean {/** * Performs a scheduled task * @param jobExecutionContext * @throws JobExecutionException */ @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("quartz task "+new Date()); }}Copy the code

Create the configuration class QuartzConfig

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail teatQuartzDetail() {return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();

    }

    @Bean
    public Trigger testQuartzTrigger(){ SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(10) RepeatForever (); // Set the time interval in seconds. RepeatForever ();return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())

                .withIdentity("testQuartz") .withSchedule(scheduleBuilder) .build(); }}Copy the code

Start the project

Using the SpringTask annotation is the most convenient way, and Quartz has become very convenient since 2.0. For these two ways, it should be said that each has its advantages, according to the need to choose. Check out the official Quartz documentation for more details

Note: The minute you think of giving up, think of the reason why you came so far.