定时任务 Timer 的学习

Timer的主要作用有以下两个:

  • 实现按指定时间执行任务
  • 实现按指定周期执行任务

Timer类的主要作用是设置计划任务,即在指定时间开始执行某一个任务。
任务使用TimerTask进行封装

基础使用:

首先要编写TimerTask的子类来定义执行的具体任务:

public class MyTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("任务执行了,时间为: "+System.currentTimeMillis());
    }
}

然后使用Timer来执行:

public class Test_1 {
    public static void main(String[] args) {
        try {
            long nowTime=System.currentTimeMillis();
            System.out.println("当前时间为 "+nowTime);
            long scheduletime=nowTime+10000;
            MyTask myTask = new MyTask();
            Timer timer=new Timer();
            Thread.sleep(1000);
            timer.schedule(myTask,new Date(scheduletime));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

可以看到,Timer使用schedule(TimerTask,Date)来在指定的日期执行指定的任务
当我们执行时,会发现在这里插入图片描述线程并未结束,而在持续运行。

线程持续运行的原因:

为什么上面执行完之后,线程并未销毁而在继续运行? ,我们往源码里走:
我们看一下Timer的构造方法:
在这里插入图片描述
在这里插入图片描述
可以看到,在构造方法中启动了一个新的线程,Timer类用这个新的线程去执行计划任务,找到thread:
在这里插入图片描述
发现是TimerThread。这是一个继承Thread的类:
在这里插入图片描述
然后去看一下该类重写的run()方法:
在这里插入图片描述
发现,里面执行的是mainloop(),那就继续往下找:
在这里插入图片描述
mainLoop() 方法里面是一个死循环,新启动的线程并不是守护线程,而且一直在运行。然后该死循环的中断核心逻辑如下:
在这里插入图片描述
当队列为空并且newTasksMayBeScheduled这个标记为true的时候,该线程就暂停运行,进行等待。下面判断队列为空时才会退出,但是如果调用schedule()方法的话队列就不可能为空,也就是当newTasksMayBeScheduled这个标记变为false时才有可能退出,那么就找到赋值false的方法:
是在cancel() 方法里面:
在这里插入图片描述
不执行 cancel() 方法,则变量newTasksMayBeScheduled的值就不会是false,进程一直呈死循环状态,进程不销毁就是这个原因

当计划时间小于当前时间

那么Timer就会立刻执行该计划任务:

public class Test_1 {
    public static void main(String[] args) {
        try {
            long nowTime=System.currentTimeMillis();
            System.out.println("当前时间为 "+nowTime);
            long scheduletime=nowTime-1000;
            MyTask myTask = new MyTask();
            Timer timer=new Timer();
            timer.schedule(myTask,new Date(scheduletime));
            Thread.sleep(3000);
            timer.cancel();
//            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

周期执行计划任务

只要调用 public void schedule(TimerTask task, Date firstTime, long period)方法即可

public class Test_1 {
    public static void main(String[] args) {
        try {
            long nowTime=System.currentTimeMillis();
            System.out.println("当前时间为 "+nowTime);
            long scheduletime=nowTime-1000;
            MyTask myTask = new MyTask();
            Timer timer=new Timer();
            timer.schedule(myTask,new Date(scheduletime),4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值