java定时任务

245 阅读2分钟

「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战

Timer

java自带的Timer

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        System.out.println("Time's up!");

    }
},3000L,1000);

解释:3000ms是延迟启动时间,1000ms是定时任务周期,每1s执行一次

Timer计时器可以定时(指定时间执行任务)、延迟(延迟5秒执行任务)、周期性地执行任务(每隔个1秒执行任务),但是,Timer存在一些缺陷。首先Timer对调度的支持是基于绝对时间的,而不是相对时间,所以它对系统时间的改变非常敏感。其次Timer线程是不会捕获异常的,如果TimerTask抛出的了未检查异常则会导致Timer线程终止,同时Timer也不会重新恢复线程的执行,他会错误的认为整个Timer线程都会取消。同时,已经被安排单尚未执行的TimerTask也不会再执行了,新的任务也不能被调度。故如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。

ScheduledThreadPool-线程池
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("=========================");
    }
}, 1000, 2000, TimeUnit.MILLISECONDS);

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis()+"<><>"+System.nanoTime());
    }
}, 1000, 2000, TimeUnit.MILLISECONDS);
使用注解的形式:@Scheduled
@Component
public class SpringScheduled {
    @Scheduled(initialDelay = 2000,fixedDelay = 5000)
    public void doSomething() {
        System.out.println("Spring自带的Scheduled执行了=======================");
    }
}

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

    public static void main(String[] args) throws InterruptedException {
        SpringApplication application = new SpringApplication(DemoApplication.class);
        application.addListeners(new ContextRefreshedEventListener());
        application.run(args);
    }
}
使用Quartz定时任务调度器
@Configuration
public class QuartzConfig {
    
    @Resource
    private ScheduleTask scheduleTask;

    /**
     * 配置定时任务1
     * @return
     */
    @Bean(name="firstJobDetail")
    public MethodInvokingJobDetailFactoryBean firstJobDetail(){
        MethodInvokingJobDetailFactoryBean method = new MethodInvokingJobDetailFactoryBean();
        // 为需要执行的实体类对应的对象
        method.setTargetObject(scheduleTask);
        // 需要执行的方法
        method.setTargetMethod("test");
        // 是否并发执行
        method.setConcurrent(false);
        return method;
    }


    /**
     *   配置触发器1
     *   @param firstJobDetail
     *   @return
     */
    @Bean(name="firstTrigger")
    public SimpleTriggerFactoryBean firstTrigger(JobDetail firstJobDetail){
        SimpleTriggerFactoryBean simpleBean = new SimpleTriggerFactoryBean();
        simpleBean.setJobDetail(firstJobDetail);
        // 设置任务启动延迟
        simpleBean.setStartDelay(1000);
        // 每1秒执行一次
        simpleBean.setRepeatInterval(1000);
        //设置重复计数
        //simpleBean.setRepeatCount(0);
        return simpleBean;
    }

    /**
     *  配置Scheduler
     */
    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactoryBean(Trigger firstTrigger){
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setTriggers(firstTrigger);
        return factoryBean;
    }
}

@Component
public class ScheduleTask {
    public void test() {
        System.out.println("====================================");
    }
}
总结
  • Quartz是执行时间和间隔时间的最大值(比如;执行时间是3s,间隔是2s,则每3s执行一次;执行时间是3s,间隔是5s,则每5s执行一次。)
  • Spring task是执行时间+间隔时间(比如;执行时间是3s,间隔是2s,则每5s执行一次;执行时间是3s,间隔是5s,则每8s执行一次。)
  • timer有2中方法schedule和scheduleAtFixedRate,前者会等任务结束在开始计算时间间隔,后者是在任务开始就计算时间,有并发的情况
  • ScheduledExecutorService的scheduleAtFixedRate类似Quartz,scheduleWithFixedDelay类似SpringTask