Java中有兩種實現多線程的方式以及兩種方式之間的區別


Java中有兩種實現多線程的方式。一是直接繼承Thread類,二是實現Runnable接口。那么這兩種實現多線程的方式在應用上有什么區別呢?

http://yuelangyc.iteye.com/blog/1056393

為了回答這個問題,我們可以通過編寫一段代碼來進行分析。我們用代碼來模擬鐵路售票系統,實現通過四個售票點發售某日某次列車的100張車票,一個售票點用一個線程表示。

我們首先這樣編寫這個程序:

 1 class ThreadTest extends Thread{
 2      private int ticket = 100;
 3      public void run(){
 4        while(true){
 5          if(ticket > 0){
 6             System.out.println(Thread.currentThread().getName() +
 7               "is saling ticket" + ticket--);
 8          }else{
 9            break;
10          }
11       }
12    }
13 }

main測試類:

1 public class ThreadDome1{
2   public static void main(String[] args){
3     ThreadTest t = new ThreadTest();
4       t.start();
5       t.start();
6       t.start();
7       t.start();
8    }
9 }

 

上面的代碼中,我們用ThreadTest類模擬售票處的售票過程,run方法中的每一次循環都將總票數減1,模擬賣出一張車票,同時該車票號打 印出來,直接剩余的票數到零為止。在ThreadDemo1類的main方法中,我們創建了一個線程對象,並重復啟動四次,希望通過這種方式產生四個線 程。從運行的結果來看我們發現其實只有一個線程在運行,這個結果告訴我們:一個線程對象只能啟動一個線程,無論你調用多少遍start()方法,結果只有 一個線程。

我們接着修改ThreadDemo1,在main方法中創建四個Thread對象:

 1 class ThreadTest extends Thread{
 2   private int ticket = 100;
 3   public void run(){
 4       while(true){
 5       if(ticket > 0){
 6       System.out.println(Thread.currentThread().getName() +
 7           " is saling ticket" + ticket--);
 8       }else{
 9          break;
10       }
11     }
12   }
13 }

 

1 public class ThreadDemo1{
2   public static void main(String[] args){
3     new ThreadTest().start();
4     new ThreadTest().start();
5     new ThreadTest().start();
6     new ThreadTest().start();
7  }
8 }

 

這下達到目的了嗎?

從結果上看每個票號都被打印了四次,即四個線程各自賣各自的100張票,而不去賣共同的100張票。這種情況是怎么造成的呢?我們需要的是,多個線程去處 理同一個資源,一個資源只能對應一個對象,在上面的程序中,我們創建了四個ThreadTest對象,就等於創建了四個資源,每個資源都有100張票,每 個線程都在獨自處理各自的資源。

經過這些實驗和分析,可以總結出,要實現這個鐵路售票程序,我們只能創建一個資源對象,但要創建多個線程去處理同一個資源對象,並且每個線程上所運行的是相同的程序代碼。在回顧一下使用接口編寫多線程的過程。

class ThreadTest implements Runnable{
  private int tickets = 100;
  public void run(){
     while(true){
     if(tickets > 0){
       System.out.println(Thread.currentThread().getName() +
          " is saling ticket " + tickets--);
      }
    }
  }
}

 

1 public class ThreadDemo1{
2   public static void main(String[] args){
3    ThreadTest t = new ThreadTest();
4      new Thread(t).start();
5      new Thread(t).start();
6      new Thread(t).start();
7      new Thread(t).start();
8   }
9 }
 
        

上面的程序中,創建了四個線程,每個線程調用的是同一個ThreadTest對象中的run()方法,訪問的是同一個對象中的變量 (tickets)的實例,這個程序滿足了我們的需求。在Windows上可以啟動多個記事本程序一樣,也就是多個進程使用同一個記事本程序代碼。

可見,實現Runnable接口相對於繼承Thread類來說,有如下顯著的好處:

(1)適合多個相同程序代碼的線程去處理同一資源的情況,把虛擬CPU(線程)同程序的代碼,數據有效的分離,較好地體現了面向對象的設計思想。

(2)可以避免由於Java的單繼承特性帶來的局限。我們經常碰到這樣一種情況,即當我們要將已經繼承了某一個類的子類放入多線程中,由於一個類不能同時有兩個父類,所以不能用繼承Thread類的方式,那么,這個類就只能采用實現Runnable接口的方式了。

(3)有利於程序的健壯性,代碼能夠被多個線程共享,代碼與數據是獨立的。當多個線程的執行代碼來自同一個類的實例時,即稱它們共享相同的代碼。 多個線程操作相同的數據,與它們的代碼無關。當共享訪問相同的對象是,即它們共享相同的數據。當線程被構造時,需要的代碼和數據通過一個對象作為構造函數 實參傳遞進去,這個對象就是一個實現了Runnable接口的類的實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM