1. 程式人生 > >Thread和Runnable你該選哪個

Thread和Runnable你該選哪個

使用多執行緒時,大家大抵都有過疑惑,到底是繼承Thread呢,還是實現Runnable介面,我也有過這樣的疑惑,於是便上網搜了下,這邊就記下我自己的見解,歡迎指正批評。

              一般使用中,很多有經驗的老程式設計師大部分都是不約而同的使用Runnable多一些,為什麼呢,我也問過公司的那些老員工,他們也說不出個所以然,只是使用經驗讓他們去這樣選擇,這裡我去檢視Thread和Runnable的原始碼,發覺Thread內部也是實現的Runnable的介面的,慢慢的好像有些頭緒,Thread類片段原始碼如下:

Java程式碼
  1. /** 
  2.     * If this thread was constructed using a separate  
  3.     * <code>Runnable</code> run object, then that 
     
  4.     * <code>Runnable</code> object's <code>run</code> method is called;  
  5.     * otherwise, this method does nothing and returns.  
  6.     * <p> 
  7.     * Subclasses of <code>Thread</code> should override this method.  
  8.     * 
  9.     * @see     #start() 
  10.     * @see     #stop()
     
  11.     * @see     #Thread(ThreadGroup, Runnable, String) 
  12.     */
  13.    publicvoid run() {  
  14. if (target != null) {  
  15.     target.run();  
  16. }  
  17.    }  

            這裡寫到如果target不為空的話,則呼叫它的run方法,這個target,則是Runnable的例項物件,也就是說,繼承於Thread並實現它的run方法能建立一個執行緒,實際這個run方法就是Runnable所提供的代理物件所有的,因此我們得到Runnable的優點之後,再拿過來跟Thread的優先一一對比,也就大體能知道,使用時,到底選用Thread好還是Runnable好點。

           經對比,Runnable的優勢有以下幾點:1.適合多個相同程式程式碼的執行緒去處理同一個資源(多執行緒內的資料共享) 2.避免java特性中的單根繼承限制  3.增加程式健壯性,資料被共享時,仍然可以保持程式碼和資料的分離和獨立  4.更能體現java面向物件的設計特點

           針對以上的特點2,3,4我們大體可以理解,而對於優勢1可能不太深刻,這邊,為了體現它在多執行緒內的資料共享方面的優勢,我們用張孝祥所舉的經典的買票例子來演示下,多個視窗同時賣票,這裡多個視窗即多個執行緒,所賣的票則是需要共享的資料。

           以下是Thread的實現方式:

Java程式碼
  1. class hello extends Thread {  
  2.     publicvoid run() {  
  3.         for (int i = 0; i < 7; i++) {  
  4.             if (count > 0) {  
  5.                 System.out.println("count= " + count--);  
  6.             }  
  7.         }  
  8.     }  
  9.     publicstaticvoid main(String[] args) {  
  10.         hello h1 = new hello();  
  11.         hello h2 = new hello();  
  12.         hello h3 = new hello();  
  13.         h1.start();  
  14.         h2.start();  
  15.         h3.start();  
  16.     }  
  17.     privateint count = 5;  
  18. }  

 執行結果為:

Java程式碼
  1. count= 5
  2. count= 4
  3. count= 3
  4. count= 2
  5. count= 1
  6. count= 5
  7. count= 4
  8. count= 3
  9. count= 2
  10. count= 1
  11. count= 5
  12. count= 4
  13. count= 3
  14. count= 2
  15. count= 1

          以上結果顯示,假使這真是一個買票系統count為總車票數的話,以上程式碼並未實現執行緒內的資料共享

下面我們看下Runnable的實現,程式碼如下:

Java程式碼
  1. class MyThread implements Runnable{  
  2.     privateint ticket = 5;  //5張票
  3.     publicvoid run() {  
  4.         for (int i=0; i<=20; i++) {  
  5.             if (this.ticket > 0) {  
  6.                 System.out.println(Thread.currentThread().getName()+ "正在賣票"+this.ticket--);  
  7.             }  
  8.         }  
  9.     }  
  10. }  
  11. publicclass lzwCode {  
  12.     publicstaticvoid main(String [] args) {  
  13.         MyThread my = new MyThread();  
  14.         new Thread(my, "1號視窗").start();  
  15.         new Thread(my, "2號視窗").start();  
  16.         new Thread(my, "3號視窗").start();  
  17.     }  
  18. }  

 執行結果為:

Java程式碼
  1. count= 5
  2. count= 4
  3. count= 3
  4. count= 2
  5. count= 1