知识点“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接口更好。