Resolved: resolved the problem of multiple timer conflicts in Spring Boot multithreading environment

Forwarding official account: IT Ranch

Tactical Analysis:

There must be more than one timer in the actual development project, which needs to be used in many scenarios, and the problem brought by multiple timers is how to avoid the conflict of multiple timers

Usage scenario:

Our order service generally has an order to be paid, which has a time limit. For example, Alibaba's order is five days, Taobao's order is one day, pinduoduo's order is one day, and meituan's order is 15 minutes

In the fund system, how to update fund information in multiple storage partitions at the same time

Generally speaking, in the actual development, timers need to solve the problem of simultaneous concurrency of multiple timers and the conflict between timers

It's not a big problem. When it comes to concurrency, it's inseparable from multithreading... Take your time to understand

Problem scenario reproduction:

We can clearly see that the execution results are all scheduling-1

It can be determined from this that the Springboot timer is single threaded by default

But the problem comes. If a thread takes a long time to execute after the thread competes for resources, what about other timers? They can only enter the waiting state. The longer the time, the more timers to wait, which is easy to cause an avalanche

In fact, you only need to add a configuration class and annotate it to solve the problem

adding annotations

The specific codes are as follows:

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

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

@Component
public class SchedulerTaskController {
    private Logger logger= LoggerFactory.getLogger(SchedulerTaskController.class);
    private static final SimpleDateFormat dateFormat=new SimpleDateFormat("HH:mm:ss");
    private int count=0;
    @Scheduled(cron="*/6 * * * * ?")
    @Async("threadPoolTaskExecutor")
    public void process(){
        logger.info("english:this is scheduler task runing "+(count++));
    }

    @Scheduled(fixedRate = 6000)
    @Async("threadPoolTaskExecutor")
    public void currentTime(){
        logger.info("chinese:present time"+dateFormat.format(new Date()));
    }
}

The configuration classes are as follows:

The specific codes are as follows:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;



/**When using multithreading, we often need to create Thread class or implement Runnable interface. If we want to use Thread pool, we also need to create Executors,
 * In using spring, it has given us good support. You can use multithreading whenever you want @ EnableAsync
 * The thread pool can be used through the ThreadPoolTaskExecutor provided by spring.*/
//@Configuration indicates that this class is a configuration class
@Configuration
@EnableAsync
//All scheduled tasks are placed in a thread pool. Different threads are used when scheduled tasks are started.
public class TaskScheduleConfig {
    private static final int corePoolSize = 10;         //Default number of threads
    private static final int maxPoolSize = 100;       //Maximum number of threads
    private static final int keepAliveTime = 10;   //Allow thread idle time (unit: the default is seconds). The thread will be shut down after ten seconds
    private static final int queueCapacity = 200;   //Number of buffer queues
    private static final String threadNamePrefix = "it-is-threaddemo-"; //Thread pool name prefix

    @Bean("threadPoolTaskExecutor") //The name of the bean. The default method name is lowercase
    public ThreadPoolTaskExecutor getDemoThread(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(keepAliveTime);
        executor.setKeepAliveSeconds(queueCapacity);
        executor.setThreadNamePrefix(threadNamePrefix);

        //Processing strategy of thread pool rejecting tasks
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //initialization
        executor.initialize();

        return executor;
    }
}

Then we can see clearly

As mentioned above, it solves the problem of using multithreading to solve the multi timer conflict of Springboot

Keywords: Java Programming Spring Spring Boot Cache

Added by anoopmail on Mon, 03 Jan 2022 08:52:55 +0200