線程中不可避免的wait/notify/notifyAll/join

在運用線程的過程中,不可避免的要遇到wait()、notify()、notifyAll()、join()這幾個方法,但是首先需要注意的是,這些方法的調用對象,前三個方法的調用對象都是object,而join方法是作爲一個Thread對象的方法調用的。

Wait()和notify方法的使用,當線程A需要等待線程B完成了某些操作之後才能繼續執行,此時線程A就可以調用obj.wait()將線程暫時進入等待狀態,在線程B完成了某些操作之後再調用obj.nofity()方法,從而A得以繼續執行,其中obJ是A和B都可見得任意的Object對象 

例如下面的代碼,第一個啓動的線程,調用了obj.wait()方法,那麼第一個啓動的線程將進入等待狀態,直到第二個線程調用了notify方法,那麼前面進入等待的線程纔會再次被啓動。

public class Test1 {
	
	public static void main(String args []){
		
		 final Object obj = new Object();
		 final boolean finished = false;
		
		 new Thread(){
			public void run() {
				System.out.println("線程1啓動了");
				synchronized(obj){
					
						try {
							System.out.println("線程1進入暫停狀態");
							obj.wait(200000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				
				System.out.println("線程1結束了");
			}
		}.start();
		
		
		new Thread(){
			public void run() {
				synchronized(obj){
					System.out.println("喚醒線程被啓動了");
				//	finished =true;
				
						obj.notifyAll();
					
						System.out.println("線程1即將再次啓動了");
					}
			
				}
			
		}.start();
		
	}
}
那麼從上面的分析可以知道控制檯輸出的結果如下

在object方法中有notifyAll()方法和notify()方法,這兩個方法的區別在於前者會喚醒前面所有進入等待狀態的線程,第二個方法只會喚醒前面所有在等待狀態線程中的第一個進入等待狀態的線程。


wait()和notify方法多用線程之間某些資源的共享,而join方法多用線程之間聯合完成某些任務。從下面的例子我們可以看出,當在主線程之中調用了線程threadone的join方法時,主線程會等待join方法參數指定的時間,在等待的時間內,主線程進入暫停狀態,在等待的時間結束之後,主線程繼續運行。例子中,還加入對線程threadone是否存活的判斷,即當threadone還是存活狀態的時候,主線程每次等待一秒鐘,如果threadone線程死掉,那麼主線程將不再等待。

package com.learnjava.jointest;

public class Jointest {

	public static void main(String args[]){
		Thread threadone = new Thread(){
			@Override
			public void run() {
				System.out.println("線程即將1啓動");
				for(int i = 0 ;i < 10 ;i++){
					try {
						System.out.println("線程1正在運行"+i);
						this.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("線程1結束運行");
			}
		};
		threadone.start();
		
		
	
		
		
		while(threadone.isAlive()){
			try {
				threadone.join(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("等待線程1結束");
		}
		System.out.println("等待結束");
	}
	
	
	
}

通常對線程不可能永遠的等下去,例如當需要等待的時間很長,我們又不想等待那麼長的時間的時候,這就需要我們根據業務邏輯調用線程的interrupte方法,用於中斷指定的線程。在下面的例子中,我們定了一個變量time.當time大於了我們的timeout的時候,threadone 將會被中斷,

package com.learnjava.jointest;

public class Jointest {

	public static void main(String args[]){
		
		int timeout = 2000;
		int time = 0;
		
		
		Thread threadone = new Thread(){
			@Override
			public void run() {
				System.out.println("線程即將1啓動");
				for(int i = 0 ;i < 1 ;i++){
					try {
					
						System.out.println("線程1正在運行"+i);
						this.sleep(10000000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("線程1結束運行");
			}
		};
		threadone.start();
		
		
	
		
		
		while(threadone.isAlive()&& time <= timeout){
			try {
				threadone.join(300);
				time += 300;
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("等待線程1結束");
		}
		
		if(time > timeout){
			threadone.interrupt();
		}
		System.out.println("等待結束");
	}
	
	
	
}


文章參考書籍:Android程序設計





發佈了31 篇原創文章 · 獲贊 31 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章