定时器

定时器:

  • 1.在约定好的时间点上,执行某个任务
  • 2.每间隔一定时间就执行某个任务

在JAVA中实现定时器功能要用的2个类是Timer,TimerTask

Timer类是用来履行任务的类,它接受1个TimerTask做参数

Timer有两种执行任务的模式,最经常使用的是schedule,它可以以以下几种方式执行任务:
1:在某个时间(Data),
2:在某个固定的时间以后(long delay).
3.间隔一定时间就执行某个任务(long period )

import java.util.concurrent.*;

/**
 * 定时器:
 * 1.在约定好的时间点上,执行某个任务
 * 2.每间隔一定时间就执行某个任务
 */
public class MyTimer {

    private BlockingQueue<Runnable> queue = new PriorityBlockingQueue();

    public MyTimer(int count) {
        for (int i = 0; i < count; i++) {
            new Thread(new MyWorker(queue)).start();
        }
    }

    /**
     * 定时任务
     * @param task  需要执行的任务
     * @param delay 从当前时间延迟多少毫秒执行任务
     * @param period  间隔时间; <=0就忽略掉,>0需要每间隔给定时间,就执行任务
     */
    public void schedule(Runnable task,long delay,long period){
        try {
            queue.put(new MyTimerTask(task,System.currentTimeMillis()+delay,period));
            synchronized (queue){
                queue.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class MyWorker implements Runnable{

        private BlockingQueue<Runnable> queue;

        public MyWorker(BlockingQueue<Runnable> queue){
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    //blockingQueue本身就是线程安全的,所以这里的方法调用不用放在同步代码块中
                    MyTimerTask task = (MyTimerTask) queue.take();
                    synchronized (queue) {

                        long current = System.currentTimeMillis();
                        if (task.next < current) {
                            queue.wait(task.next-current );
                            queue.put(task);
                        } else {
                            task.task.run();
                            if (task.period > 0) {
                                task.next = task.next + task.period;
                                queue.put(task);
                            }
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static class MyTimerTask implements Runnable,Comparable<MyTimerTask>{

        //定时任务
        private Runnable task;
        //下次执行时间
        private long next;
        private long period;
        public MyTimerTask(Runnable task,long next,long period){
            this.task = task;
            this.next = next;
            this.period = period;
        }

        @Override
        public void run() {

        }

        @Override
        public int compareTo(MyTimerTask o) {
            return 0;
        }
    }
    
    public static void main(String[] args) {

        new MyTimer(4).schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("起床了");
            }
        },3000,1000);
    }
}

这里主要用了一个MyTimer来表示一个定时器,使用BlockingQueue阻塞队列来存储任务和执行时间(delay),间隔执行时间(period),并使用内部类MyTimerTask将他们传给阻塞队列queue,同时使用内部类MyWorker来执行任务

首先main方法启动4个线程,然后MyTimer调用 MyWorker并传入了一个阻塞式队列并启动,
然后定时器就会从阻塞队列中取出任务,即queue.take();但是如果当前时间大于下次执行时间,说明定时器仍需等待,直到下次执行时间到来,同时要将该任务放回阻塞队列并阻塞等待.
而如果时间已到,则执行任务,若间隔执行任务的时间(period)>0,则下次任务执行时间需要延长period,同样这里应该使用synchronized关键字加锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

运笔如飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值