自制定时器

本文介绍了如何自定义一个名为didadida的定时器工具,满足每隔一定延迟后执行指定任务的需求。基础版是一个抽象类,用户需自行实现执行内容,但由于在同一线程中,任务执行会影响定时精度。进阶版通过使用独立线程执行任务,解决了这一问题,确保定时器计时不被任务执行影响。
摘要由CSDN通过智能技术生成

自己编写一个定时器工具叫做didadida工具吧。
需求:每隔几秒(delay)后,执行我提供的一个任务(task)。

基础版

这是一个抽象类,每隔几秒需要执行的内容是要用户自己完成的。

public abstract class simple implements Runnable{
	private static final int DEAULT_DELAY = 1000;
	private volatile boolean goon;
	private Object lock = new Object();
	private int delay;
	
	public simple() {
		this(DEAULT_DELAY);
	}
	public simple(int delay) {
		this.delay = delay;
		goon = false;
	}
	public void setDealy(int delay) {
		this.delay = delay;
	}
	public void start() {
		if(goon == true) {
			return;
		}
		new Thread(this).start();
		goon = true;
	}
	public void stop() {
		if(goon == false) {
			return;
		}
		goon = false;
	}
	
	//任务
	public abstract void doSomething();
	
	@Override
	public void run() {
		while(goon) {
			//这里其实是单线程执行的,并没有多线程问题。
			//但是我选用了object.wait()方法,必须要在同步代码块中。
			//至于为什么不用Thread.sleep()。因为sleep比较耗cpu。
			synchronized(lock) {
				try {
					//当前线程睡眠delay毫秒之后执行dosomething
					lock.wait(delay);
					doSomething();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

测试代码

public static void main(String[] agrs) {
		simple simpleDida = new simple(400) {
			@Override
			public void doing() {
				try {
					Thread.sleep(100);
					System.out.println(System.currentTimeMillis());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		
		simpleDida.start();
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		simpleDida.stop();
	}

只打印了10次,因为是单线程执行,doSomething方法和didadida计时器方法是同一个线程,所以soSomething方法也会占用时间。上述代码执行一个轮回就是400+100毫秒。

最简单的解决方案就是soSomething用一个线程来跑。
下面进阶版

进阶版

这个版本的定时器,由于doSomething();是另一个线程再跑,所以执行这个方法时,不会影响定时器的计时。

@Override
	public void run() {
		while(goon) {
			synchronized(lock) {
				try {
					lock.wait(delay);
					new something();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	class something implements Runnable{
		public something() {
			new Thread(this).start();
		}
		
		@Override
		public void run() {
			doSomething();
		}
	}
JAVA精确定时器,利用系统时间,使长期工作的误差稳定。 功能: ·可定时启动任务或直接启动任务 ·重复启动任务(时间间隔可在任务线程中改变,范围大于100ms,否则精度降低) 引用列表: ·import psn.razerpen.thread.AccuracyTimer; ·import psn.razerpen.thread.AccuracyTimerMission; ·import psn.razerpen.time.TimeStruct; 使用方法: //1·继承AccuracyTimerMission接口,创建一个类。 class MyTimer implements AccuracyTimerMission { //2·指定一个周期 int nDelay=1000; //3·重写run方法(如不需要使用新线程执行任务,也可留空) /** * 任务线程,本函数继承自Runnable */ @Override public void run() { System.out.println(new TimeStruct()); } //4·重写RunInCurrentThread(long nCurrentMilliSecond)方法。该方法接收当前时间,并返回下一次执行的时间。如果返回值不大于nCurrentMilliSecond则中止计时器。该方法必须重写。 /** * 接收当前时间的毫秒值,并返回下一次执行的毫秒值。如果返回的下一个时间早于当前时间,则退出 */ @Override public long RunInCurrentThread(long nCurrentMilliSecond) { return nCurrentMilliSecond+=nDelay; } } //5·创建主线程代码 public class TestTimer { public static void main(String[] args) throws InterruptedException { //6·创建一个AccuracyTimer对象,并指定一个任务。 AccuracyTimer at=new AccuracyTimer(new MyTimer()); //7·(可选)如果不需要在新线程中启动任务,则写 // at.SetNewThreadEnabled(false); //否则不写或者写 // at.SetNewThreadEnabled(true); //8·(可选)设定第一次启动的时间点SetNextMissionTime/SetNextMissionMilliSecond或延迟时间SetNextMissionMilliSecondFromNow //设置为当前这一分钟的第59秒后启动(不写此行则表示直接启动) at.SetNextMissionTime(Integer.MIN_VALUE, -1, -1, -1, -1, 59, 0); //9·启动定时器 at.Start(); //10·主线程继续 for(int i=0;i<60;++i){ Thread.sleep(1000); } //11·结束定时器 at.End(); } } 详见sample.razerpen.thread包中TestTimer及各代码文件中注释
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值