滴答滴答 ——Java计时器

Java计时器

作用:

计时器也就是用来计时的东西。当你需要隔一段时间去干一件事的时候就可以用到它,比如:

当某拼夕夕网站的抢购在一段规定的时间内需要结束时。
比如某宝的页面需要在一段规定的时间里刷新页面时。
当你设置的闹钟在规定时间将你叫醒。

实现原理:

Thread.sleep(long millis);调用此方法可以让线程实现millis时间长度的睡眠。

代码显示:

package com.dxc.simple_dida.core.core;

public interface ISimpleDiDa {
    
    
	void doSomething();
}

package com.dxc.simple_dida.core.core;

public class SimpleDiDa implements Runnable, ISimpleDiDa{
    
    
	
	private long delayTime;
	private boolean goon;//当goon为TRUE线程启动,为false线程关闭。
	int count;
	
	public SimpleDiDa() {
    
    
	}

	//设置线程休眠时间
	public void setDelayTime(long delayTime) {
    
    
		this.delayTime = delayTime;
	}
	
	//启动线程
	public void startup() {
    
    
		this.goon = true;	
		new Thread(this).start();
	}
	
	//计时器以规定的时间间隔
	public void run() {
    
    
		while (goon) {
    
    
			try {
    
    
				Thread.sleep(this.delayTime);
				doSomething();//这里可以执行接口里面的方法
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
		}
	}
	
	//停止线程
	public void stop() {
    
    
		this.goon = false;
	}

	//设置接口方法实现的内容
	//这里我输出一下时间,时间单位为毫秒
	@Override
	public void doSomething() {
    
    
		System.out.println("第" + ++this.count
				+ "次执行:" + System.currentTimeMillis());
	}
}

测试代码:

package com.dxc.simple_dida.core.core;

public class Test {
    
    

	public static void main(String[] args) {
    
    
		SimpleDiDa sdd = new SimpleDiDa();
		sdd.setDelayTime(1000);	//设置线程执行时间间隔为一秒
		sdd.startup();//启动线程
		try {
    
    
			Thread.sleep(10000);
			//让主函数睡眠十秒钟,以便执行上面启动的线程
			sdd.stop();//主函数休眠结束,关闭执行线程
		} catch (InterruptedException e) {
    
    
			e.printStackTrace();
		}
	}
}

测试结果

执行结果
主函数休眠了十秒钟,所以线程执行了十次。每次线程执行的结果间隔应该为一秒,但结果我们可以看到第二次和第三次执行的结果间隔了1001毫秒。第六次和第七次间隔了1002毫秒。

在startup(),即,启动定时器时,令goon为真,并创建一个线程,这个线程处于死循环状态,以便能多次执行doSomething();
且,每次总是先休眠delayTime毫秒,再执行doSomething(),其实也就是每个delayTime毫秒,启动执行用户的任务。

但是,这个思路依然存在问题:因为sleep()方法之后执行了doSomething(),且,只有在doSomething()执行完毕后,才能进入下一轮计时,使得两次执行用户任务之间的时间间隔应该是:
delayTime + 用户任务所耗时间

上述错误的根本原因是:不应该在时间到达时执行用户任务,而是“启动”用户任务!在成功启动用户任务后,立刻继续重新计时!
这就要求,对于用户任务,应该再用一个线程执行之!

执行用户代码的接口

package com.dxc.senior_dida.core;

public interface ISeniorDiDa extends Runnable{
    
    
	@Override
	default void run() {
    
    
		doSomething();
	}
	
	void doSomething();
}

package com.dxc.senior_dida.core;

public class SeniorDiDa implements Runnable {
    
    
	public static final long DEFAULT_DELAY_TIME = 1000;
	
	private long delayTime;
	private volatile boolean goon;
	private ISeniorDiDa worker;//用户执行的代码
	
	public SeniorDiDa() {
    
    
		this.delayTime = DEFAULT_DELAY_TIME;
	}
	
	//添加用户执行代码
	public SeniorDiDa setWorker(ISeniorDiDa worker) {
    
    
		this.worker = worker;
		return this;
	}

	public SeniorDiDa setDelayTime(long delayTime) {
    
    
		this.delayTime = delayTime;
		return this;
	}

	//启动线程
	public void startup() {
    
    
		if (this.goon == true) {
    
    
			return;
		}
		if (this.worker == null) {
    
    
			return;
		}
		this.goon = true;
		new Thread(this).start();
	}
	
	//关闭线程
	public void stop() {
    
    
		if (this.goon == false) {
    
    
			return;
		}
		this.goon = false;
	}
	
	@Override
	public void run() {
    
    
		while (goon) {
    
    
			try {
    
    
				//线程睡眠delaytime时间
				Thread.sleep(this.delayTime);
				//线程睡眠期间,启动并执行用户要执行的代码
				new Thread(this.worker).start();
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
		}
	}
	
}

测试代码

package com.dxc.senior_dida.core;

public class Test {
    
    

	public static void main(String[] args) {
    
    
		//设置用户要执行的代码
		ISeniorDiDa worker = new ISeniorDiDa() {
    
    
			private int count = 0;
			
			@Override
			public void doSomething() {
    
    
				System.out.println("第" + ++this.count
						+ "次执行:" + System.currentTimeMillis());
			}
		};
		
		SeniorDiDa seniorDiDa = new SeniorDiDa()
				.setWorker(worker);
		seniorDiDa.startup();//启动线程
		try {
    
    
			Thread.sleep(10000);//主函数睡眠10000毫秒
			seniorDiDa.stop();//线程停止
		} catch (InterruptedException e) {
    
    
			e.printStackTrace();
		}
	}

}

猜你喜欢

转载自blog.csdn.net/adaizzz/article/details/109268076