Directory
- Brief introduction
- First, the Application launch task
- Second, the JDK comes with the scheduling thread pool
- Third, @Scheduled
- Custom @Scheduled thread pool
- Iv. @Async
- Custom @Async thread pool
- Summary
Brief introduction
Most applications are dependent on timers, which typically require some special processing tasks during program startup and during run time.
such as resource initialization, data statistics, and so on, springboot as a flexible framework, there are many ways to implement a timer or asynchronous task.
I summed up the following, roughly there are several:
-
- Using the timertask of the JDK
-
- Using the JDK to bring the scheduler thread pool
-
- Using the Quartz scheduling framework
-
- Using @Scheduled, @Async annotations
One of the first methods to use TimerTask is not recommended, because there is a risk of hanging timertask when the system time jumps .
The third use of the Quartz scheduling framework can achieve very powerful timer functions, including distributed scheduling timers and so on.
Consider the way in which most scenarios are used, and the following pages will focus on the second and fourth types.
First, the Application launch task
When the Springboot application is started, the initialization tasks can be implemented through the following two interfaces:
- Commandlinerunner
- Applicationrunner
The difference between the two is small, the only difference is:
Commandlinerunner receives a set of process command startup parameters in string form;
The Applicationrunner receives a parsed encapsulated parameter body object.
For a detailed comparison, look at the code:
public class CommandLines { private static final Logger logger = LoggerFactory.getLogger(CommandLines.class); @Component @Order(1) public static class CommandLineAppStartupRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { logger.info( "[CommandLineRunner]Application started with command-line arguments: {} .To kill this application, press Ctrl + C.", Arrays.toString(args)); } } @Component @Order(2) public static class AppStartupRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { logger.info("[ApplicationRunner]Your application started with option names : {}", args.getOptionNames()); } }}
Second, the JDK comes with the scheduling thread pool
In order to achieve timing scheduling, it is necessary to use scheduledthreadpoolexecutor
The code for initializing a thread pool is as follows:
/** * 构造调度线程池 * * @param corePoolSize * @param poolName * @return */ public static ScheduledThreadPoolExecutor newSchedulingPool(int corePoolSize, String poolName) { ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(corePoolSize); // 设置变量 if (!StringUtils.isEmpty(poolName)) { threadPoolExecutor.setThreadFactory(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread tr = new Thread(r, poolName + r.hashCode()); return tr; } }); } return threadPoolExecutor; }
You can specify corepoolsize to be greater than 1 to implement concurrent execution of scheduled tasks.
For use in Springboot projects, we use a commandlinerunner to achieve:
@Component@Order(1)public class ExecutorTimer implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(ExecutorTimer.class); private ScheduledExecutorService schedulePool; @Override public void run(String... args) throws Exception { logger.info("start executor tasks"); schedulePool = ThreadPools.newSchedulingPool(2); schedulePool.scheduleWithFixedDelay(new Runnable() { @Override public void run() { logger.info("run on every minute"); } }, 5, 60, TimeUnit.SECONDS); }}
Schedulepool.schedulewithfixeddelay Specifies that the dispatch task executes at a fixed frequency.
Third, @Scheduled
@Scheduled is a way for Spring3.0 to implement scheduling tasks based on annotations.
You need to enable this feature by @EnableScheduling annotations before you use it.
The code is as follows:
/** * 利用@Scheduled注解实现定时器 * * @author atp * */@Componentpublic class ScheduleTimer { private static final Logger logger = LoggerFactory.getLogger(ScheduleTimer.class); /** * 每10s */ @Scheduled(initialDelay = 5000, fixedDelay = 10000) public void onFixDelay() { logger.info("schedule job on every 10 seconds"); } /** * 每分钟的0秒执行 */ @Scheduled(cron = "0 * * * * *") public void onCron() { logger.info("schedule job on every minute(0 second)"); } /** * 启用定时器配置 * * @author atp * */ @Configuration @EnableScheduling public static class ScheduleConfig { }}
Description
The above code shows how the two timers are used:
The first way
Specify initial delay (initialdelay), fixed delay (fixeddelay);
The second way
Defined by a cron expression
This is similar to the definition of the unix/linux system crontab, which allows for very flexible customization.
Examples of some cron expressions:
An expression |
Description |
0 0 * * * * |
The first hour of every day |
/10 * * * * |
Every 10 seconds |
0 0 8-10 * * * |
Daily 8, 9, 10 o'clock on the hour |
0 * 6,19 * * * |
6 points per day and 19 points every minute |
0 0/30 8-10 * * * |
Daily 8:00, 8:30, 9:00, 9:30 10:00 |
0 0 9-17 * * MON-FRI |
9 to 17 on weekdays |
0 0 0 25 12? |
Every year at midnight on Christmas Eve |
Custom @Scheduled thread pool
By default, tasks that @Scheduled annotations are dispatched by a single thread pool.
This causes the timer tasks within the app to be executed serially only.
In order to achieve a scheduled task concurrency, or more detailed customization,
You can use the schedulingconfigurer interface.
The code is as follows:
@Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskExecutor()); } @Bean(destroyMethod="shutdown") public Executor taskExecutor() { //线程池大小 return Executors.newScheduledThreadPool(50); } }
Iv. @Async
The meaning of @Async annotation is to change the way the Bean method executes to an asynchronous way.
For example, when a front-end request is processed, the results can be returned in advance by asynchronous execution.
Similarly, this annotation needs to be used in conjunction with @EnableAsync annotations.
The code is as follows:
@Configuration @EnableAsync public static class ScheduleConfig { }
Using @Async to implement simulation tasks
@Componentpublic class Asynctimer implements Commandlinerunner {private static final Logger Logger = Logger Factory.getlogger (Asynctimer.class); @Autowired Private Asynctask task; @Override public void Run (String ... args) throws Exception {Long T1 = System.currenttimemillis (); Task.doasyncwork (); Long t2 = System.currenttimemillis (); Logger.info ("Async timer execute in {} MS", T2-T1); } @Component public static class Asynctask {private static final Logger Logger = Loggerfactory.getlogger (Asy Nctask.class); @Async public void Doasyncwork () {Long T1 = System.currenttimemillis (); try {thread.sleep ((long) (Math.random () * 5000)); } catch (Interruptedexception e) {} Long t2 = System.currenttimemillis (); Logger.info ("Async task execute in {} MS", T2-T1); } }
In the sample code, Asynctask waits for a random time to end.
The Asynctimer executes the task.doasyncworkand will return early.
The results of the implementation are as follows:
- async timer execute in 2 ms- async task execute in 3154 ms
it 's important to note that asynchronous implementations are actually implemented through Spring's AOP capabilities.
The effect is not achieved for calls between Asynctask internal methods.
Custom @Async thread pool
The asyncconfigurer interface is required for customization of the @Async thread pool.
The code is as follows:
@Configuration @EnableAsync public static class ScheduleConfig implements AsyncConfigurer { @Bean public ThreadPoolTaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); //线程池大小 scheduler.setPoolSize(60); scheduler.setThreadNamePrefix("AsyncTask-"); scheduler.setAwaitTerminationSeconds(60); scheduler.setWaitForTasksToCompleteOnShutdown(true); return scheduler; } @Override public Executor getAsyncExecutor() { return taskScheduler(); } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; } }
Summary
Timed asynchronous task is an application common request, this article collects several common implementation methods.
As a springboot application, the use of annotations is the most convenient.
Here we explain the @Scheduled, @Async a few common annotations,
and provide a way to customize its thread pool, hoping to have some help to the reader.
Welcome to continue to pay attention to "American Code Division tutorial Series-springboot article", if you feel that the old driver's article is not bad, please share forwarding ^-^
Tutorial Series (9)-springboot timer, did you use the right one?