ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

@Schedule执行定时任务

2022-07-25 12:00:34  阅读:129  来源: 互联网

标签:INFO 25 test2 07 Schedule ExecuteSequence 任务 2022 定时


@Shcedule默认情况下会单线程顺序执行。如果一个定时任务执行时间大于其任务间隔时间,那么下一次将会等待上一次执行结束后再继续执行。如果多个定时任务在同一时刻执行,任务会依次执行。

1. 单线程顺序执行demo:

 

package com.citi.ark.mls.timer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
@Slf4j
//@EnableAsync

public class ExecuteSequence {
    @Scheduled(cron = "0/3 * * * * ?")
//    @Async
    public void test1() throws InterruptedException {
        Long current=System.currentTimeMillis();
        log.info("===this is test1 start:{}===",current);
        Thread.sleep(9900);
        log.info("===this is test1 end:{}===",System.currentTimeMillis()-current);
//        log.info("==test1 output:{}",i++);
    }

    @Scheduled(cron = "0/3 * * * * ?")
//    @Async
    public void test2() throws InterruptedException {
        Long current=System.currentTimeMillis();
        log.info("===this is test2 start:{}===",current);
        Thread.sleep(5000);
        log.info("===this is test2 end:{}===",System.currentTimeMillis()-current);
//        log.info("==test2 output:{}",i++);
    }

    private Integer getResult(int i){
        int j=i++;
        return j;
    }
}

 

执行结果如下,可见是单线程顺序执行

2022-07-22 18:08:27.013 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test1 start:1658484507013===
2022-07-22 18:08:37.027 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test1 end:10014===
2022-07-22 18:08:37.029 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test2 start:1658484517028===
2022-07-22 18:08:42.037 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test2 end:5009===
2022-07-22 18:08:42.039 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test1 start:1658484522038===
2022-07-22 18:08:52.041 c.c.a.m.t.ExecuteSequence scheduling-1 [INFO] ===this is test1 end:10003===

 

2. 异步方式处理——利用Spring提供的@Async注解和@EnableAsync注解

demo 1 中效率会比较低

package mls.timer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@EnableAsync
public class ExecuteSequence {
@Scheduled(cron = "0/3 * * * * ?")
@Async
public void test1() throws InterruptedException {
Long current=System.currentTimeMillis();
log.info("===this is test1 start:{}===",current);
Thread.sleep(10000);
log.info("===this is test1 end:{}===",System.currentTimeMillis()-current);
// log.info("==test1 output:{}",i++);
}

@Scheduled(cron = "0/3 * * * * ?")
@Async
public void test2() throws InterruptedException {
Long current=System.currentTimeMillis();
log.info("===this is test2 start:{}===",current);
Thread.sleep(5000);
log.info("===this is test2 end:{}===",System.currentTimeMillis()-current);
// log.info("==test2 output:{}",i++);
}

private Integer getResult(int i){
int j=i++;
return j;
}
}
执行结果如下,由于test1/test2执行时间是5s>任务调度周期3s,发生上一个任务未执行完毕下一个任务又开始执行逻辑,从如下执行结果可以明显可出。所以最好执行方式是采用多线程自己控制线程数据量

2022-07-25 11:38:18.030 c.c.a.m.t.ExecuteSequence task-1 [INFO] ===this is test2 start:1658720298030===
2022-07-25 11:38:18.030 c.c.a.m.t.ExecuteSequence task-2 [INFO] ===this is test1 start:1658720298030===  //
2022-07-25 11:38:21.007 c.c.a.m.t.ExecuteSequence task-3 [INFO] ===this is test1 start:1658720301007===  //上一个test1还没end下一个test1又开始了
2022-07-25 11:38:21.007 c.c.a.m.t.ExecuteSequence task-4 [INFO] ===this is test2 start:1658720301007===
2022-07-25 11:38:23.036 c.c.a.m.t.ExecuteSequence task-1 [INFO] ===this is test2 end:5006===
2022-07-25 11:38:24.015 c.c.a.m.t.ExecuteSequence task-5 [INFO] ===this is test2 start:1658720304015===
2022-07-25 11:38:24.016 c.c.a.m.t.ExecuteSequence task-6 [INFO] ===this is test1 start:1658720304016===
2022-07-25 11:38:26.021 c.c.a.m.t.ExecuteSequence task-4 [INFO] ===this is test2 end:5014===
2022-07-25 11:38:27.002 c.c.a.m.t.ExecuteSequence task-7 [INFO] ===this is test2 start:1658720307002===
2022-07-25 11:38:27.003 c.c.a.m.t.ExecuteSequence task-8 [INFO] ===this is test1 start:1658720307003===
2022-07-25 11:38:28.037 c.c.a.m.t.ExecuteSequence task-2 [INFO] ===this is test1 end:10007===
2022-07-25 11:38:29.025 c.c.a.m.t.ExecuteSequence task-5 [INFO] ===this is test2 end:5010===
2022-07-25 11:38:30.011 c.c.a.m.t.ExecuteSequence task-1 [INFO] ===this is test1 start:1658720310011===
2022-07-25 11:38:30.011 c.c.a.m.t.ExecuteSequence task-4 [INFO] ===this is test2 start:1658720310011===
2022-07-25 11:38:31.012 c.c.a.m.t.ExecuteSequence task-3 [INFO] ===this is test1 end:10005===
2022-07-25 11:38:32.013 c.c.a.m.t.ExecuteSequence task-7 [INFO] ===this is test2 end:5011===
2022-07-25 11:38:33.003 c.c.a.m.t.ExecuteSequence task-2 [INFO] ===this is test1 start:1658720313003===
2022-07-25 11:38:33.003 c.c.a.m.t.ExecuteSequence task-5 [INFO] ===this is test2 start:1658720313003===
2022-07-25 11:38:34.025 c.c.a.m.t.ExecuteSequence task-6 [INFO] ===this is test1 end:10009===
2022-07-25 11:38:35.015 c.c.a.m.t.ExecuteSequence task-4 [INFO] ===this is test2 end:5004===
2022-07-25 11:38:36.012 c.c.a.m.t.ExecuteSequence task-3 [INFO] ===this is test1 start:1658720316012===
2022-07-25 11:38:36.012 c.c.a.m.t.ExecuteSequence task-7 [INFO] ===this is test2 start:1658720316012===
2022-07-25 11:38:37.008 c.c.a.m.t.ExecuteSequence task-8 [INFO] ===this is test1 end:10005===

 

3. 多线程执行  -- 自定义线程池 @EnableScheduling

demo2采用@Async 和@EnableAsync方式,每次定时任务启动都会创建一个单独的线程来处理,也就是说同一个定时任务(比如下例中test1)也会启动多个线程处理

首先需要实现SchedulingConfigurer接口,然后自定义线程池,这样凡是用到@Scheduled注解的都可以用该线程池
package com.citi.ark.mls.timer;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer{
@Bean
public Executor executors() {
return Executors.newScheduledThreadPool(5,(Runnable r) ->{
Thread thread=new Thread(r);
thread.setName("ScheduleThread");
return thread;
});
}

@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(executors());
}
}
package com.citi.ark.mls.timer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class ExecuteSequence {
@Scheduled(cron = "0/3 * * * * ?")
@Async
public void test1() throws InterruptedException {
Long current=System.currentTimeMillis();
log.info("===this is test1 start:{}===",current);
Thread.sleep(10000);
log.info("===this is test1 end:{}===",System.currentTimeMillis()-current);
// log.info("==test1 output:{}",i++);
}

@Scheduled(cron = "0/3 * * * * ?")
@Async
public void test2() throws InterruptedException {
Long current=System.currentTimeMillis();
log.info("===this is test2 start:{}===",current);
Thread.sleep(5000);
log.info("===this is test2 end:{}===",System.currentTimeMillis()-current);
// log.info("==test2 output:{}",i++);
}

private Integer getResult(int i){
int j=i++;
return j;
}
}

执行结果如下,可以看到test2在thread3未执行完之前并不会执行下一个test2任务,即解决了同一个任务启动多个线程处理问题

2022-07-25 11:32:48.008 c.c.a.m.t.ExecuteSequence Thread-3 [INFO] ===this is test2 start:1658719968008===
2022-07-25 11:32:48.008 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 start:1658719968008===
2022-07-25 11:32:53.010 c.c.a.m.t.ExecuteSequence Thread-3 [INFO] ===this is test2 end:5002===
2022-07-25 11:32:54.006 c.c.a.m.t.ExecuteSequence Thread-3 [INFO] ===this is test2 start:1658719974006===
2022-07-25 11:32:58.016 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 end:10008===
2022-07-25 11:32:59.019 c.c.a.m.t.ExecuteSequence Thread-3 [INFO] ===this is test2 end:5013===
2022-07-25 11:33:00.000 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 start:1658719980000===
2022-07-25 11:33:00.016 c.c.a.m.t.ExecuteSequence Thread-6 [INFO] ===this is test2 start:1658719980016===
2022-07-25 11:33:05.029 c.c.a.m.t.ExecuteSequence Thread-6 [INFO] ===this is test2 end:5013===
2022-07-25 11:33:06.012 c.c.a.m.t.ExecuteSequence Thread-6 [INFO] ===this is test2 start:1658719986012===
2022-07-25 11:33:10.015 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 end:10015===
2022-07-25 11:33:11.020 c.c.a.m.t.ExecuteSequence Thread-6 [INFO] ===this is test2 end:5008===
2022-07-25 11:33:12.007 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 start:1658719992007===
2022-07-25 11:33:12.007 c.c.a.m.t.ExecuteSequence Thread-5 [INFO] ===this is test2 start:1658719992007===
2022-07-25 11:33:17.012 c.c.a.m.t.ExecuteSequence Thread-5 [INFO] ===this is test2 end:5004===
2022-07-25 11:33:18.002 c.c.a.m.t.ExecuteSequence Thread-5 [INFO] ===this is test2 start:1658719998002===
2022-07-25 11:33:22.022 c.c.a.m.t.ExecuteSequence Thread-4 [INFO] ===this is test1 end:10015===
2022-07-25 11:33:23.011 c.c.a.m.t.ExecuteSequence Thread-5 [INFO] ===this is test2 end:5009===

 

标签:INFO,25,test2,07,Schedule,ExecuteSequence,任务,2022,定时
来源: https://www.cnblogs.com/enhance/p/16506776.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有