Implementation of simple task scheduling in spring

1 Introduction

The two kinds of task scheduling in spring are timing and asynchronous tasks, which are only supported in a single machine environment. If you want to be in a distributed environment, you can use quartz, XXX job and so on.

2. Scheduled task scheduling

@Enable scheduling annotation enables support for Scheduled tasks. You can use @ Scheduled annotation to implement Scheduled tasks based on some timing strategies such as corn, fixedRate, fixedDelay, etc

  • a. The interval time of fixedDelay control method execution is calculated from the beginning of the last method execution. If the last method execution is blocked, the next execution will be performed until the last execution is completed and the interval is given.
  • b. fixedRate is executed at a certain rate. It starts from the time of the last method execution. If the last method is blocked, it will not be executed next time. However, during the blocking period, the cumulative number of times should be executed. When it is no longer blocked, it will be executed all at once, and then continue to execute at a fixed rate.
  • c. cron expressions can be customized to perform tasks, similar to fixed delay. It will start from the end time of the last method. cron expression configuration: https://www.pppet.net/
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
	taskRegistrar.setScheduler(threadPoolTaskScheduler());
    }

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
	ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
	executor.setPoolSize(20);
	executor.setThreadNamePrefix("ScheduleExecutor-");
	executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
	// Wait for the currently scheduled task to complete when scheduler shutdown is called
	executor.setWaitForTasksToCompleteOnShutdown(true);
	// Waiting time
	executor.setAwaitTerminationSeconds(60);
	return executor;
    }

}

@Component
public class NormalScheduledTask {
    /**
     * Similar to fixedDelay. It will start from the end time of the last method.
     */
    @Scheduled(cron = "0/5 * * * * *")
    public void work2() {
        System.out.println("Every 5 seconds" + LocalDateTime.now());
    }
    /**
     * fixedDelay The interval between the execution of the control method is calculated from the beginning of the execution of the above method. If the execution of the previous method is blocked, the next execution will be performed until the last execution is completed and after the given interval.
     * 
     */
    @Scheduled(fixedDelay = 1000*3)
    public void work1() {
	 System.out.println("Every 3 seconds");
    }
    /**
     * When the execution time of the method exceeds the task scheduling frequency, the scheduler will execute the next task immediately after the execution of the current method.
     *  
     */
    @Scheduled(fixedRate = 1000*2)
    public void work3() {
	 System.out.println("Every 2 seconds");
    }
}

To dynamically modify timing configuration rules:

@Component
public class DynamicScheduledTask {
    private static final Logger logger = LoggerFactory.getLogger(DynamicScheduledTask.class);
    private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);

    // Unified management of scheduling classes by using established
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    /**
     * New scheduled task
     * @param task
     * @param cronExpression
     */
    public void addCronTask(Runnable task, String cronExpression) {
        addCronTask(new CronTask(task, cronExpression));
    }


    /**
     * Remove scheduled tasks
     * @param task
     */
    public void removeCronTask(Runnable task) {
        ScheduledTask scheduledTask = this.scheduledTasks.remove(task);
        if (scheduledTask != null)
            scheduledTask.cancel();
    }

    private ScheduledTask scheduleCronTask(CronTask cronTask) {
        ScheduledTask scheduledTask = new ScheduledTask();
        scheduledTask.future = this.threadPoolTaskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());

        return scheduledTask;
    }
    private void addCronTask(CronTask cronTask) {
        if (cronTask != null) {
            Runnable task = cronTask.getRunnable();
            if (this.scheduledTasks.containsKey(task)) {
                removeCronTask(task);
            }

            this.scheduledTasks.put(task, scheduleCronTask(cronTask));
        }
    }

    @PreDestroy
    public void destroy() {
        for (ScheduledTask task : this.scheduledTasks.values()) {
            task.cancel();
        }
        this.scheduledTasks.clear();
    }

}

//Test:
   Runnable task = new Runnable() {
	    @Override
	    public void run() {
		System.out.println("In execution" + LocalDateTime.now());

	    }

	};
	dynamicScheduledTask.addCronTask(task, "0/2 * * * * ?");
	
	Thread.sleep(10000);
	//Change the scheduled task of the task to execute every 3 seconds.
	dynamicScheduledTask.addCronTask(task, "0/3 * * * * ?");

3. Asynchronous task execution

@Enable Async to enable asynchronous support. Use @ Async to execute a method asynchronously

@Configuration
@EnableAsync  //Implement asynchronous tasks
public class ThreadPoolTaskConfig {
	
	private static final int corePoolSize = 10;       		// Number of core threads (default number of threads) number of threads initialized when the thread pool was created
	private static final int maxPoolSize = 100;			    // Maximum number of threads the maximum number of threads in the thread pool. Only after the buffer queue is full can the threads that exceed the number of core threads be applied
	private static final int keepAliveTime = 10;			// Allow thread idle time (in seconds by default) threads beyond the core thread will be destroyed when the idle time reaches
	private static final int queueCapacity = 200;			// Number of buffered queues used to buffer the queues executing tasks
	private static final String threadNamePrefix = "Async-Service-"; // The prefix of thread pool name is convenient for us to locate the thread pool where the processing task is located
	
	@Bean("taskExecutor") // The name of the bean. The default method name is lowercase
	public ThreadPoolTaskExecutor taskExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);   
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.setKeepAliveSeconds(keepAliveTime);
		executor.setThreadNamePrefix(threadNamePrefix);
		
		// The thread pool adopts the CallerRunsPolicy policy for the processing policy of the rejected task. When the thread pool has no processing power, the policy will run the rejected task directly in the calling thread of the execute method. If the executing program is closed, the task will be discarded
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		// initialization
		executor.initialize();
		return executor;
	}

}
@Component
@Async
public class AsyncTask {
    
 
    //Get asynchronous results
    public Future<String> task4() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(2000L);
        long end = System.currentTimeMillis();
        System.out.println("Task 4 time consuming="+(end-begin));
        return new AsyncResult<String>("Task 4");
    }
    
    
    public Future<String> task5() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(3000L);
        long end = System.currentTimeMillis();
        System.out.println("Task 5 time consuming="+(end-begin));
        return new AsyncResult<String>("Task 5");
    }
    
    public Future<String> task6() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(1000L);
        long end = System.currentTimeMillis();
        System.out.println("Task 6 time consuming="+(end-begin));
        return new AsyncResult<String>("Task 6");
    }
        

}

Tags: Programming Spring

Posted on Tue, 05 May 2020 14:51:33 -0400 by Thuy