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