栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Scheduled的简单使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Scheduled的简单使用

Scheduled的简单使用

我们在开发中往往会遇到很多需要定时任务的请求,比如每天晚上凌晨去请求接口等。而且我们也不需要特别复杂的需求,比如需要什么分布式场景,这样我们可以用Spring的Scheduled。

下面的示例我用的是Springboot的项目

首先在启动类上添加@EnableScheduling 注解

先简单测试一个一个用例

import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

@Component
public class RunIntervalTestScheduler {

    @Scheduled(cron = "0/1 * * * * ?")
    public void singleThreadTest1() {
        log.info("singleThreadTest1");
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    }

    @Scheduled(cron = "0/1 * * * * ?")
    public void singleThreadTest2() {
        log.info("singleThreadTest2");
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    }


    @Scheduled(initialDelay = 1000, fixedRate = 100000)
    public void singleThreadTest3() {
        log.info("singleThreadTest3");
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    }

}

还需要添加一个配置类信息,目的是为了开启一个异步调度

@Configuration
public class ScheduledConfig implements SchedulingConfigurer {

    
    private static final int TASK_POOL_SIZE = 50;
    
    private static final String TASK_THREAD_PREFIX = "test-task-";

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler taskPool = new ThreadPoolTaskScheduler();
        taskPool.setPoolSize(TASK_POOL_SIZE);
        taskPool.setThreadNamePrefix(TASK_THREAD_PREFIX);
        taskPool.initialize();
        scheduledTaskRegistrar.setTaskScheduler(taskPool);
    }
}

结果如下:

其中,@Scheduled注解支持cron表达式,fixedRate表示上一次的任务调度和下一次任务调度的间隔时间。

然而,我们在实际开发中,往往需要将这个定时实际通过参数传过去。而不是写在配置文件中。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;

@Controller
public class TestScheduler {

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        return new ThreadPoolTaskScheduler();
    }

    private ScheduledFuture future;


    @RequestMapping("/startCron")
    @ResponseBody
    public String startCron(@RequestParam("cron") Long cron){
        System.out.println("x0");
        
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("2022-04-18 16:12:00");
        future = threadPoolTaskScheduler.schedule(new Say("123"), new Date(System.currentTimeMillis()+10000));

        System.out.println("x1");
        return "x";
    }

    @RequestMapping("/stopCron")
    @ResponseBody
    public String stopCron(){
        System.out.println("stop >>>>>");
        if(future != null) {
            future.cancel(true);
        }
        //future = threadPoolTaskScheduler.schedule(new Say(), new CronTrigger("*/5 * * * * *"));
        System.out.println("stop <<<<<");
        return "stop cron";
    }

}

解读一下上面的代码:

startCron(Long cron)方法的参数cron需要接口的请求里传一个时间戳,我们将请求的参数cron转化为Date格式,调用threadPoolTaskScheduler.schedule,有人可能会有疑问,直接传cron表达式不好嘛?Scheduled支持的cron表达式默认是6位,不支持传年,所以如果请求参数传cron表达式,很有可能每年的这个时间都会执行一次。

调用接口ip:port/stopCron 会停止这个调度的执行

细心的小伙伴可能发现了这个new Say(“123”);这个是一个线程。

public class Say implements Runnable {

    private String str;

    Say(String str){
        this.str = str;
    }

    @Override
    public void run(){
        System.out.println("" + new Date() + " hello" );
        test(str);
    }

    void test(String str){
        System.out.println("开始打印"+str);
    }
}

我们可以传一个实际用的参数,调用test方法,test方法对应我们正常的业务代码,这里有一个点值得注意,那就是如果这个类Say里面需要其他的Service注入,那么只能以构造函数的方式,因为这个类上没有加@bean的注解,在Spring进行扫描的时候不会认为它是一个Bean。这个坑我之前就遇到过。



我们可以传一个实际用的参数,调用test方法,test方法对应我们正常的业务代码,这里有一个点值得注意,那就是如果这个类Say里面需要其他的Service注入,那么只能以构造函数的方式,因为这个类上没有加@bean的注解,在Spring进行扫描的时候不会认为它是一个Bean。这个坑我之前就遇到过。







转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/841757.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号