Java中的定时器Timer的用法

发布时间:2021-08-16 15:03:21 作者:chen
来源:亿速云 阅读:142

这篇文章主要介绍“Java中的定时器Timer的用法”,在日常操作中,相信很多人在Java中的定时器Timer的用法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中的定时器Timer的用法”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

简单来说,定时器就相当于一个“闹钟”,给定时器设定一个任务,约定这个任务在xxx时间之后执行~

Timer类提供了一个核心接口,schedule(安排) 指定一个任务交给定时器,在一定时间之后再去执行这个任务~

如何实现定时器的效果~

具体如何用代码实现这样一个定时器Timer:

一般去设定时间的时候,传入的时间,都是一个时间间隔

例如:传入1000 ,就代表从当前开始过1000ms之后在执行;

而我这里为了后面代码方便判断,在这里记录一下绝对时间,这样this.time里就是一个标志的ms级时间戳了,后续只需要获取当前时间戳在和这里的time对比一下就好了。

Java中的定时器Timer的用法

Task 要放到一个优先级队列中,但是优先级队列里面是需要比较优先级的,所以可以让Task类实现Comparable接口,重写compareTo方法来进行比较。

Java中的定时器Timer的用法

这里希望时间较小的排在见面。

Java中的定时器Timer的用法

这里获取一下当前时间currTime,如果当前时间大于等于task里约定的时间,超过说明时间到,执行任务,反之没到,把取去的

任务再放回队列,继续等待。

Java中的定时器Timer的用法

这里还涉及到一个问题:

举个例子:假如你早上定了一个8.30的 闹钟,8点的时候你醒了,看了下时间,还没到,你就继续睡,

但是这里是while(true),就意味着每过一秒钟就要看一次闹钟,8.01看一次,8.02看一次,这样就会白白的浪费一些资源,这就出现了“盲等”,在等待任务时间的过程中,一直持有着CPU资源~

所以这里就需要优化一下:使用wait/notify机制,就可很好的改善盲等问题~

如果取出任务发现还没到时间,就wait,等待一定时间,这里使用的wait()的重载版本,wait()里写一个参数,达到等待时间,自动醒过来~ 此时就大大降低了扫描次数和成本,

Java中的定时器Timer的用法

这里的notify(),就是保证当线程中如果有线程在WAITING状态的线程,就需要显示的唤醒一下线程。

举个例子;

如果队首元素8.30在执行,等待30分钟,但是此时,可能突然插入一个任务,让你8.10的时候去干一件事,如果你8.30再去唤醒的话,8.10的任务就来不及了!

所以每次插入新任务的时候,都唤醒一下woeker线程,让worker线程重新获取一下队首元素,看看接下来的任务等待多少时间合适。

Java中的定时器Timer的用法

//简单定时器
public class TestTimer {
    //每个 Task 实例 就包含一个要执行的任务
    //Task 要放到一个优先级队列中,但是优先级队列里面是需要比较优先级的
    static class Task implements Comparable<Task>{
        //什么时候执行
        private long time;
        //执行什么任务
        private  Runnable command;

        public Task(Runnable command ,long time){
            this.command = command;
            this.time = System.currentTimeMillis()+time;
        }

        public void  run(){
        //执行Runable 里面的run方法
            command.run();
        }

        @Override
        public int compareTo(Task o) {
            return (int)(this.time - o.time);
        }
    }
    static class Timer{
        //先创建一个带优先级的阻塞队列
        private PriorityBlockingQueue<Task>  queue = new PriorityBlockingQueue<>();

        //用这个对象来完成线程之间的协调任务
        private Object meilbox = new Object();

        //schedule 方法就是把一个Task 放在Timer中
        public void schedule(Runnable command,long after){
            Task task = new Task(command,after);
            //将当前任务放入对列
            queue.put(task);
            //当worker 线程中包含wait机制的时候,在安排任务的时候就需要显示的唤醒一下
            synchronized (meilbox){
                meilbox.notify();
            }
        }
        //写一个构造方法,创建线程
        public Timer(){
            //创建一个线程,让这个线程去扫描队列的队首元素,看看能不能执行
            Thread worker = new Thread(){
                @Override
                public void run() {
                    //取出队首元素,判断这个元素能不能执行
                    while(true){
                        try {
                            Task task = queue.take();
                            long currTime = System.currentTimeMillis();
                            if(currTime >= task.time){
                                //时间到,执行任务
                                task.run();
                            }else{
                                //时间没到,继续等待
                                queue.put(task);
                                synchronized (meilbox){
                                    meilbox.wait(task.time-currTime);
                                }
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            worker.start();
        }
    }
}

测试:

public static void main(String[] args) {
        Timer timer = new Timer();
        Runnable command = new Runnable() {
            @Override
            public void run() {
                System.out.println("时间到了~");
               // timer.schedule(this,3000); 每隔3是就执行一次
            }
        };
        System.out.println("安排任务");
        timer.schedule(command,3000);
    }
}

安排任务后,等待3s就可以执行了

Java中的定时器Timer的用法

这里补充一下Timer原生类中的一些方法

到此,关于“Java中的定时器Timer的用法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. python线程定时器Timer的用法
  2. 线程:Timer定时器

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Numpy数组怎么实现组合与分割

下一篇:JavaScript数组怎么合并

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》