Java併發基礎02:傳統線程技術中的定時器技術

歡迎關注個人微信公衆號:程序員私房菜(id:eson_15)java

傳統線程技術中有個定時器,定時器的類是Timer,咱們使用定時器的目的就是給它安排任務,讓它在指定的時間完成任務。因此先來看一下Timer類中的方法(主要看經常使用的TimerTask()方法):程序員

返回值 方法名 方法描述
void schedule(TimerTask task, long delay) 安排在指定延遲後執行指定的任務。
void schedule(TimerTask task, long delay, long period) 安排指定的任務從指定的延遲後開始進行重複的固定延遲執行。
void schedule(TimerTask task, Date time) 安排在指定的時間執行指定的任務
void schedule(TimerTask task, Date firstTime, long period) 安排指定的任務在指定的時間開始進行重複的固定延遲執行。

前面兩個是在指定延遲後執行或者重複執行,後面兩個是在指定時間執行或者重複執行。咱們之前兩個爲例來研究一下定時器的使用。微信

先寫一個簡單的使用定時器的demo,而後慢慢引伸。ide

public class TraditionalTimer {

	public static void main(String[] args) {
		//簡單定時器的demo
		new Timer().schedule(new TimerTask() {			
			@Override
			public void run() {
				//實際中會扔一個對象進來,咱們就能夠在這裏操做這個對象的全部方法了
				System.out.println("--boom--");//爆炸
			}
		}, 2000,3000); 

		//打印秒鐘,一秒輸出一次,用來方便觀察的
		while(true) {
			System.out.println(new Date().getSeconds());
			try {
				Thread.sleep(1000);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
複製代碼

咱們用匿名內部類來定義了一個TimerTask對象,須要重寫run()方法,而後運行這個程序,能夠看出來第一次2秒鐘後打印「--boom--,後面每隔3秒打印一次。spa

咱們也能夠本身來實現上面這個重複執行,咱們用定時器的「連環套」!也就是定時器中再套定時器,一個定時器任務執行完了,在任務的最後再裝一個定時器。那麼咱們須要先定義一個本身的定時器任務,在本身的定時器任務中再裝一個定時器,把自定義的定時器任務扔進去。而後咱們開啓定時器的時候把本身定義的定時器任務扔進去便可。以下:線程

public class TraditionalTimer {

	public static void main(String[] args) {
		
		//自定義一個定時器任務
		class MyTimerTask extends TimerTask {			
			@Override
			public void run() {
				System.out.println("--boom--");
				//任務執行完再裝一個定時器,扔進自定義的定時器任務
				new Timer().schedule(new MyTimerTask(), 3000);
			}
		}
		new Timer().schedule(new MyTimerTask(), 2000);//外面開啓定時器
		
		while(true) {//打印秒鐘,一秒輸出一次
			System.out.println(new Date().getSeconds());
			try {
				Thread.sleep(1000);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
複製代碼

這樣的話,咱們經過定時器的「連環套」很輕鬆的實現了連環爆炸。可是如今問題來了,上面提供的方法中重複執行都是每隔固定的時間,若是我想要隔2秒執行一次,再隔4秒執行一次,再隔2秒執行一次,再隔4秒執行一次……這該如何實現呢?code

能夠這樣,咱們定義一個全局的私有成員變量來記錄爆炸次數,奇數的時候隔2秒炸,偶數的次數的話隔4秒炸,或者反過來也行,修改以下:cdn

public class TraditionalTimer {

	private static int count = 0; //記錄爆炸的次數
	public static void main(String[] args) {	

		class MyTimerTask extends TimerTask {			
			@Override
			public void run() {
				count = (count + 1) % 2; //結果只有0和1
				System.out.println("--boom--");
				new Timer().schedule(new MyTimerTask(), 2000+2000*count);//根據count結果設定新的定時時間
			}
		}
		new Timer().schedule(new MyTimerTask(), 2000);
		
		while(true) {//打印秒鐘,一秒輸出一次
			System.out.println(new Date().getSeconds());
			try {
				Thread.sleep(1000);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
複製代碼

這樣的話,咱們就實現了自定義爆炸間隔了。上面這個是經過定義一個全局私有變量來實現,其實咱們也能夠這麼幹:不是要實現兩個不一樣時間間隔的連環炸麼?我能夠定義兩個定時器任務A和B,在A執行完開啓定時器,把B任務裝進去,B執行完開啓定時器把A裝進去,這樣也能夠。以下:對象

public class TraditionalTimer {

	public static void main(String[] args) {
		
		new Timer().schedule(new MyTimerTaskA(), 2000);//A和B隨便開一個
		
		while(true) {//打印秒鐘,一秒輸出一次
			System.out.println(new Date().getSeconds());
			try {
				Thread.sleep(1000);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}

}
//自定義兩個定時器任務類,繼承TimerTask便可
class MyTimerTaskA extends TimerTask {

	@Override
	public void run() {
		System.out.println("--boomA--");
		new Timer().schedule(new MyTimerTaskB(), 4000);
	}			
}
class MyTimerTaskB extends TimerTask {

	@Override
	public void run() {
		System.out.println("--boomB--");
		new Timer().schedule(new MyTimerTaskA(), 2000);
	}	
}
複製代碼

這樣就能夠實現自定義時間間隔的連環炸了。傳統的定時器技術就總結這麼多吧~若是有問題,歡迎指正,咱們一同進步!繼承

也歡迎你們關注個人微信公衆號:程序員私房菜。我會持續輸出更多文章。

公衆號
相關文章
相關標籤/搜索