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()" 來開啓線程

             兩種方法實現一樣的工做可是它們之間仍是有一些區別的。spa

             它們之間的不一樣是:線程

              1.咱們都知道,Java是單繼承機制,不容許同時繼承多個類。所以,當你繼承Thread類(extends Thread)後,你就不能再繼承其餘類了。而你實現Runnable接口就不同了,你能夠繼承其餘類了。code

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

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

              用一個例子來幫助咱們理解:繼承

             

 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接口更好。

相關文章
相關標籤/搜索