1. 程式人生 > >Thread和Runnable的區別和聯絡、多次start一個執行緒會怎麼樣

Thread和Runnable的區別和聯絡、多次start一個執行緒會怎麼樣

一、Java有兩種方式實現多執行緒,第一個是繼承Thread類,第二個是實現Runnable介面。他們之間的聯絡:

    1、Thread類實現了Runable介面。

  2、都需要重寫裡面Run方法。

二、實現Runnable介面相對於繼承Thread類來說,有如下顯著的好處:

 

  1、適合多個相同程式程式碼的執行緒去處理同一資源的情況,把虛擬CPU(執行緒)同程式的程式碼,資料有效的分離,較好地體現了面向物件的設計思想。 

  2、可以避免由於Java的單繼承特性帶來的侷限。我們經常碰到這樣一種情況,即當我們要將已經繼承了某一個類的子類放入多執行緒中,由於一個類不能同時有兩個父類,所以不能用繼承Thread類的方式,那麼,這個類就只能採用實現Runnable介面的方式了。 



  3、有利於程式的健壯性,程式碼能夠被多個執行緒共享,程式碼與資料是獨立的。當多個執行緒的執行程式碼來自同一個類的例項時,即稱它們共享相同的程式碼。多個執行緒操作相同的資料,與它們的程式碼無關。當共享訪問相同的物件是,即它們共享相同的資料。當執行緒被構造時,需要的程式碼和資料通過一個物件作為建構函式實參傳遞進去,這個物件就是一個實現了Runnable介面的類的例項。

看一下以繼承Thread的賣票例子:

 
class MyThread extends Thread{  
    private int ticket = 5;  
    public void run(){  
    	 while(true){
    		 System.out.println("Thread ticket = " + ticket--);  
             if(ticket < 0){  
                break;
             }  
         }  
    }  
}  
public static void main(String[] args) {					
	new MyThread().start();
	new MyThread().start();
			
}

  輸出結果:

Thread ticket = 5
Thread ticket = 5
Thread ticket = 4
Thread ticket = 4
Thread ticket = 3
Thread ticket = 2
Thread ticket = 3
Thread ticket = 1
Thread ticket = 2
Thread ticket = 0
Thread ticket = 1
Thread ticket = 0

 從結果可以看出:建立了兩個多執行緒物件,他們分別實現了買票任務; 

實現Runnable介面的賣票例子:

class MyThread2 implements Runnable{  
    private int ticket = 5;  
    public void run(){  
    	 while(true){
    		 System.out.println("Runnable ticket = " + ticket--);  
             if(ticket < 0){  
                break;
             }  
         } 
    }  
}  


<pre name="code" class="html">public static void main(String[] args) {
	MyThread2 m=new MyThread2();
	  new Thread(m).start();
	  new Thread(m).start();
		
			
}

輸出結果:

1 Runnable ticket = 5
2 Runnable ticket = 4
3 Runnable ticket = 3
4 Runnable ticket = 2
5 Runnable ticket = 1
6 Runnable ticket = 0

從結果可以看出雖然我們聲明瞭兩個執行緒,但是一共賣了6張票。他們實現了資源共享。PS:在實際開發中,一定要注意命名規範,其次上面實現Runable介面的例子由於同時操作一個資源,會出現執行緒不安全的情況,如果情況需要,我們需要進行同步操作。

三、執行緒多次呼叫start方法,引發的異常  

   通過呼叫Thread類的start()方法來啟動一個執行緒,這時此執行緒是處於就緒狀態,並沒有執行。然後通過此Thread類呼叫方法run()來完成其執行操作的,這裡方法run()稱為執行緒體,它包含了要執行的這個執行緒的內容,Run方法執行結束,此執行緒終止,而CPU再執行其它執行緒,而如果直接用Run方法,這只是呼叫一個方法而已,程式中依然只有主執行緒--這一個執行緒,其程式執行路徑還是隻有一條,這樣就沒有達到寫執行緒的目的。

  一個執行緒物件只能呼叫一次start方法.從new到等待執行是單行道,所以如果你對一個已經啟動的執行緒物件再呼叫一次start方法的話,會產生:IllegalThreadStateException異常.

  可以被重複呼叫的是run()方法。
  Thread類中run()和start()方法的區別如下:
    run()方法:在本執行緒內呼叫該Runnable物件的run()方法,可以重複多次呼叫;
    start()方法:啟動一個執行緒,呼叫該Runnable物件的run()方法,不能多次啟動一個執行緒;