Spring boot multithreading task execution

Keywords: Java

I. problem description

Task scheduled tasks are executed by single thread by default. If there are many scheduled tasks, many tasks may not be executed on time and accurately. Examples are as follows:

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TaskTest {
    private final Logger log = LoggerFactory.getLogger(TaskTest02.class);
    //Output time format
    private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:sss");

    @Scheduled(cron = "0/15 * * * * ? ")
    private void sayHello(){
        String dateTime = format.format(new Date());
        log.info("{} A greeting to the universe: Hello World!", dateTime);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(cron = "0/16 * * * * ? ")
    private void sayHello2(){
        String dateTime = format.format(new Date());
        log.info("{} A greeting to the universe: Hello,world", dateTime);
    }
}

When the sayHello() method is executing, because the task execution thread is occupied for a long time, sayHello2() is forced to delay execution backward, as shown in the figure:

II. Solutions

Option 1

Add the following code block, which can be placed in any class. Only one code block needs to be added in the whole project

@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    // Set the scheduler execution thread to 3
    scheduler.setPoolSize(3);
    return scheduler;
}

Option 2 (personal recommendation)

Just add a configuration class, and the scheduled task class or method does not need to be changed

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/**
 * @Description: multithreading scheduled tasks
 * @Date: May 28, 2019
 */
@Configuration
public class TaskConfig {
    /**
     * @Description: all scheduled tasks are placed in a thread pool, and different threads are used when the scheduled task is started
     * @return
     * @Date: May 28, 2019
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        // Set the scheduler execution thread to 3
        scheduler.setPoolSize(3);
        return scheduler;
    }
}
Option 3

Add a configuration class (implement the SchedulingConfigurer interface), and the scheduled task class or method does not need to be changed

import java.util.concurrent.Executors;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
 * @Description: multithreading scheduled tasks
 * @Date: May 27, 2019
 */
@Configuration
public class SchedulingConfig implements SchedulingConfigurer {
    /**
     * @Description: all scheduled tasks are placed in a thread pool, and different threads are used when the scheduled task is started
     * @param taskRegistrar
     * @Date: May 27, 2019
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //Set a timed task thread pool to 3
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
    }
}

III. implementation results

You can see that two timing tasks have been executed by different threads

Posted by reecec on Sun, 03 Nov 2019 07:49:55 -0800