Tutorial Series (9)-springboot timer, did you use the right one?

Source: Internet
Author: User

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:

      1. Using the timertask of the JDK
      1. Using the JDK to bring the scheduler thread pool
      1. Using the Quartz scheduling framework
      1. 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:

    1. Commandlinerunner
    2. 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?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.