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 the 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 the use of 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 the idle time of the thread (unit: the default is seconds), and close the thread 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 conflict of multiple timers in Springboot