java定时器

一、@Scheduled注解

这是基于注解可实现定时任务。

实现:

1、

@EnableScheduling注解到定时方法的类上,或者直接注解到启动类。

2、

@Scheduled注解到定时方法上
@Scheduled有以下参数:
1     @Scheduled(fixedDelay = 3000) //方法执行完成后等待3秒再次执行
2     @Scheduled(fixedRate = 3000)  //方法每隔3秒执行一次
3     @Scheduled(initialDelay = 2000,fixedRate = 4000) //延迟2秒执行第一次,之后每隔4秒执行一次
4     @Scheduled(fixedDelayString ="${time.demo}") //可以执行配置文件中的,方法执行完成后等待time.demo再次执行
5     @Scheduled(fixedRateString ="${time.demo}" ) //可以执行配置文件中的,法每隔time.demo执行一次
6     @Scheduled(cron = "0 0,30 0,8 ? * ? ")   //cron表达式,方法在每天的8点30分0秒执行,参数为字符串类型

cron表达式,推荐看这篇文章:https://www.jianshu.com/p/1defb0f22ed1

示例:

每隔3秒执行一次。

复制代码
1 @Component
2 @EnableScheduling
3 public class testScheduled {
4     
5     @Scheduled(fixedRate = 3000)
6     public void call(){
7         System.out.println("每隔3秒打印一次");
8     }
9 }
复制代码

优点:简单,只需要两个注解即可

缺点:参数和方法都必须写到代码里面

 

二、Timer().schedule创建任务

直接上示例,2秒后执行第一次,然后每隔4秒执行一次。

复制代码
 1 @Component
 2 public class testTimer {
 3     {
 4         doTimer();
 5     }
 6     public void doTimer(){
 7         //创建timer对象
 8         Timer timer = new Timer();
 9         //创建TimerTask对象
10         TimerTask timerTask = new TimerTask() {
11             //重写run方法,就是具体定时做什么事情
12             @Override
13             public void run() {
14                 System.out.println(new Date().toString());
15             }
16         };
17         //timer来执行timerTask
18         timer.schedule(timerTask,2000,4000);
19     }
20 }
复制代码

几个概念:

Timer:即定时器,为java自带的工具类,提供定时执行任务的相关功能

timer有3个核心方法:

1、添加任务(6种)

复制代码
schedule(TimerTask task, long delay):指定任务task,在delay毫秒延迟后执行
schedule(TimerTask task, Date time):指定任务task,在time时间点执行一次
schedule(TimerTask task, long delay, long period):指定任务task,延迟delay毫秒后执行第一次,并在之后每隔period毫秒执行一次
schedule(TimerTask task, Date firstTime, long period):指定任务task,在firstTime的时候执行第一次,之后每隔period毫秒执行一次
scheduleAtFixedRate(TimerTask task, long delay, long period):作用与schedule一致
scheduleAtFixedRate(TimerTask task, Date firstTime, long period):作用与schedule一致
实际上最后都会使用sched(TimerTask task, long time, long period),即指定任务task,在time执行第一次,之后每隔period毫秒执行一次

schedule使用系统时间计算下一次,即System.currentTimeMillis()+period

而scheduleAtFixedRate使用本次预计时间计算下一次,即time + period

对于耗时任务,两者区别较大,请按需求选择,瞬时任务无区别。
复制代码

2、取消任务方法:cancel(),会将任务队列清空,并堵塞线程,且不再能够接受任务(接受时报错),并不会销毁本身的实例和其内部的线程。

3、净化方法:purge(),净化会将队列里所有被取消的任务移除,对剩余任务进行堆排序,并返回移除任务的数量。

TimerTask:实际上就是一个Runnable而已,继承Runnable并添加了几个自定义的参数和方法,说白了就是在这里面写定时的具体方法。

TaskQueue:即任务队列,Timer生产任务,然后推到TaskQueue里存放,等待处理,被处理掉的任务即被移除掉。

注:TaskQueue实质上只有一个长度为128的数组用于存储TimerTask、一个int型变量size表示队列长度、以及对这两个数据的增删改查。

TimerThread:即定时器线程,线程会共享TaskQueue里面的数据,TimerThread会对TaskQueue里的任务进行消耗。

注:TimerThread实际上就是一个Thread线程,会不停的监听TaskQueue,如果队列里面有任务,那么就执行第一个,并将其删除(先删除再执行)。

三、线程

1、通过线程的sleep来造成延时的效果

示例1:thread + runnable

复制代码
 1 @Component
 2 public class testThreadAndRunnable {
 3     
 4     private Integer count = 0;
 5     
 6     public testThreadAndRunnable() {
 7         test1();
 8     }
 9     public void test1() {
10         new Thread(() -> {
11             while (count < 10) {
12                 System.out.println(new Date().toString() + ": " + count);
13                 count++;
14                 try {
15                     Thread.sleep(3000);
16                 } catch (InterruptedException e) {
17                     e.printStackTrace();
18                 }
19             }
20         }).start();
21     }
22 }
复制代码

示例2:线程池 + runnable

复制代码
 1 @Component
 2 public class testThreadPool {
 3     private static final ExecutorService threadPool = Executors.newFixedThreadPool(5);// 线程池
 4     private Integer count = 0;
 5     public testThreadPool() {
 6         test2();
 7     }
 8     public void test2() {
 9         threadPool.execute(() -> {
10             while (count < 10) {
11                 System.out.println(new Date().toString() + ": " + count);
12                 count++;
13                 try {
14                     Thread.sleep(3000);
15                 } catch (InterruptedException e) {
16                     e.printStackTrace();
17                 }
18             }
19         });
20     }
21 }
复制代码

 

2、使用ScheduledTask + runnable

示例:
复制代码
@Component
public class testScheduledTask {
    private Integer count = 0;
    @Autowired
    private TaskScheduler taskScheduler;
    public testScheduledTask(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
        test4();
        test5();
        test6();
    }
    //设置间隔时间,每2秒执行一次
    public void test4() {
        taskScheduler.scheduleAtFixedRate(() -> {
            System.out.println(new Date().toString() + ": " + count+"设置间隔时间2秒");
            count++;
        }, 2000);
    }
    //可以用Cron表达式,每天凌晨1点执行
    public void test5() {
        taskScheduler.schedule(() -> {
            System.out.println(new Date().toString() + ": " + count+"凌晨1点执行");
            count++;
        }, new CronTrigger("0 0 1 * * ?"));
    }
    //设置间隔时间,每5.5秒执行一次
    public void test6() {
        taskScheduler.scheduleAtFixedRate(() -> {
            System.out.println(new Date().toString() + ": " + count+"设置间隔时间5.5秒");
            count++;
        }, 5500);
    }
}
复制代码

 

四、Quartz

1、导入Quartz的jar包

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>

2、实现的整体结构

2.1、创建定时任务对象的Job

复制代码
//创建定时任务的对象
public class MyQuartz implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        Date date = new Date();
        String format = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(date);
        System.out.println("======响应时间为:"+format);
    }
}
复制代码

2.2、创建执行类

复制代码
@Component
public class MySchedule {
    public MySchedule() throws SchedulerException {
        doQ();
    }
    public void doQ() throws SchedulerException {
        //1、调度器Scheduler的创建
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        //2、创建JobDetail实例,并绑定执行类
        JobDetail job = JobBuilder.newJob(MyQuartz.class).withIdentity("Quartz1", "QuartzGroup1").build();
        //3、构建Trigger实例
        CronTrigger build = TriggerBuilder.newTrigger().withIdentity("Trigger1", "QuartzTrigger1")
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule("2/3 * * * * ? *"))
                .build();
        //4、执行Quartz
        scheduler.scheduleJob(job,build);
        scheduler.start();
    }
复制代码

corn表达式生成地址:https://cron.qqe2.com/

上述corn表达式指,2秒后开始执行,每3秒执行一次。

2.3、可以通过一些延时操作来控制任务停止时间

//5.利用TimeUnit实现延时操作
        TimeUnit.SECONDS.sleep(30);
        //6.关闭定时任务
        scheduler.shutdown();
        System.out.println("定时任务结束!");

Quartz参考博客:https://blog.csdn.net/qq_41011626/article/details/113740186

其他参考博客:(118条消息) 【JAVA定时器】四种常见定时器的原理和简单实现_Echo-YeZi的博客-CSDN博客_java 定时器

posted @   巴啦啦小花总  阅读(1898)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示