实现一个定时器

1.标准库中的定时器

public class Test {
	public static void main(String[] args) {
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				System.out.println("时间到1");
			}
		}, 3000);

		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				System.out.println("时间到2");
			}
		}, 4000);

		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				System.out.println("时间到3");
			}
		}, 5000);
		System.out.println("开始记时");
	}
}

image.png
知识点:

  1. 调用schedule方法安排任务
  2. image.png第一个参数是要执行的任务,TimerTask实现了Runnable接口,咱们需要继承TimerTask,重写run方法。第二个参数表示多长时间之后执行,时间单位是ms。
  3. 一个定时器可以安排多个任务,底层使用堆来存放任务
  4. Timer内部有一组线程来执行这些任务,这些线程是前台线程,只有所有前台线程都结束了,进程才会退出

2.实现一个定时器MyTimer

Java中的Timer类实现原理是通过一个TimerTask类表示定时任务,该类中有一个延迟时间的属性,已经一个run方法,用于表示定时任务要执行的操作。使用TaskQueue来存储所有的TimerTask对象,并使用TaskThread线程扫描TaskQueue取出TimerTask.

class MyTask implements Comparable<MyTask>{
	//要执行的任务
	private Runnable runnable;
	//什么时间执行任务
	private long time;

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

	public long getTime() {
		return time;
	}

	public Runnable getRunnable() {
		return runnable;
	}

	@Override
	public int compareTo(MyTask o) {
		return (int) (this.time - o.time);
	}
}
class MyTimer {
	private BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

	Object locker = new Object();
	//创建一个扫描线程,取出队列中的任务
	public MyTimer() {
		Thread t = new Thread(() -> {
			while (true) {
				try {
					//1.使用wait需要先加锁
					//2.多线程下,如果在t1线程执行到take之后,wait之前,这个任务要阻塞1小时,此时t2线程put一个任务
					//需要半小时后执行,此时notify就不会唤醒wait,导致新任务无法执行,所以需要把下面代码都加锁
					synchronized (locker) {
						//取出任务
						MyTask task = queue.take();
						//判断任务是否达到执行时间
						long curTime = System.currentTimeMillis();
						if(curTime >= task.getTime()) {
							//执行任务
							task.getRunnable().run();
						}else {
							//没到执行时间,放回队列中
							queue.put(task);
							//等待到时间到
							locker.wait(task.getTime() - curTime);
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		t.start();
	}

	public void schedule(Runnable runnable, long after) throws InterruptedException {
		MyTask myTask = new MyTask(runnable, after);
		queue.put(myTask);
		synchronized (locker) {
			locker.notify();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

指挥部在下面

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

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

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

打赏作者

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

抵扣说明:

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

余额充值