Java 中的“implements Runnable” 和“extends Thread”


  •       知識點

              “implements Runnable” 和“extends Thread”的不同

     

  •       具體分析

          最近在學習Android中的Handler消息傳遞機制時,創建新線程有兩種方式:一種是實現Runnable接口(implements Runnable)而另一種則是繼承Thread類(extends Thread)。而這兩種方式有什么異同呢?帶着這個疑問,Google了一些資料出來,本着分享給大家同時也方便自己查閱復習,寫一篇文章來記錄它。

 

     

         首先看看這兩種方式都是怎樣的?

       

 1 public class ThreadA implements Runnable {
 2     public void run() {
 3         //Code
 4     }
 5 }
 6 //調用 "new Thread(threadA).start()" 來開啟線程
 7 
 8 public class ThreadB extends Thread {
 9     public ThreadB() {
10         super("ThreadB");
11     }
12     public void run() {
13         //Code
14     }
15 }
16 //調用 "threadB.start()" 來開啟線程

             兩種方法實現同樣的工作但是它們之間還是有一些區別的。

             它們之間的不同是:

              1.我們都知道,Java是單繼承機制,不允許同時繼承多個類。因此,當你繼承Thread類(extends Thread)后,你就不能再繼承其他類了。而你實現Runnable接口就不一樣了,你可以繼承其他類了。

              2.當你繼承Thread類時,你的每一個Thread對象創造不同的對象然后關聯它們。

而繼承Runnable接口則不一樣,多個線程共享一個對象。

              用一個例子來幫助我們理解:

             

 1 class ImplementsRunnable implements Runnable {
 2  
 3      private int counter = 0;
 4  
 5     public void run() {
 6     counter++;
 7     System.out.println("ImplementsRunnable : Counter : " + counter);
 8     }
 9  }
10  
11  class ExtendsThread extends Thread {
12  
13    private int counter = 0;
14  
15  public void run() {
16    counter++;
17    System.out.println("ExtendsThread : Counter : " + counter);
18  }
19  }
20  
21  public class ThreadVsRunnable {
22  
23  public static void main(String args[]) throws Exception {
24  //多線程共享一個對象
25    ImplementsRunnable rc = new ImplementsRunnable();
26    Thread t1 = new Thread(rc);
27    t1.start();
28    Thread.sleep(1000); // 在開啟下個線程前先等待1秒
29    Thread t2 = new Thread(rc);
30    t2.start();
31    Thread.sleep(1000); // 在開啟下個線程前先等待1秒
32    Thread t3 = new Thread(rc);
33    t3.start();
34  
35  //為每一個線程創造新的實例
36    ExtendsThread tc1 = new ExtendsThread();
37    tc1.start();
38    Thread.sleep(1000); // 在開啟下個線程前先等待1秒
39    ExtendsThread tc2 = new ExtendsThread();
40    tc2.start();
41    Thread.sleep(1000); // 在開啟下個線程前先等待1秒
42    ExtendsThread tc3 = new ExtendsThread();
43    tc3.start();
44  }
45  }

運行結果:

           

          從運行的結果,我們可以看出。實現Runnable接口,只創建了一個類的實例,而且被多個線程共享了。因此Counter遞增。而繼承Thread類,你必須為每一個線程創建不同的實例。因此每個類的實例分配了不同的內存空間,每一個有不同的Counter,它們的值相同。這意味着沒有增加因為沒有一個對象的引用是相同的。

         那什么時候用Runnable接口呢?

         當你想要在一組線程中訪問相同的資源時,使用Runnable接口。在這種情況下要避免使用Thread類,因為多對象的創建會占用更多的內存,會導致大的性能花費。

          PS:Thread類內部實現了Runnable接口

          最后,哪種方式最好用呢?

             顯而易見,當然是實現Runnable接口更好。


免責聲明!

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



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