天天看點

java、android線程extends Thread 與 implements Runnable 的差別

1、通過實作Runnable接口建立線程

(1).定義一個類實作Runnable接口,重寫接口中的run()方法。在run()方法中加入具體的任務代碼或處理邏輯。

(2).建立Runnable接口實作類的對象。

(3).建立一個Thread類的對象,需要封裝前面Runnable接口實作類的對象。(接口可以實作多繼承)

(4).調用Thread對象的start()方法,啟動線程

[java]  view plain copy

  1. public class ThreadFromRunnable implements Runnable {  
  2.     //static int count = 10;  
  3.     public void run() {  
  4.         int count = 10;  
  5.         System.out.println("\t#"+Thread.currentThread().getName()+" got count from " + count);  
  6.         while(count > 0)  
  7.         {  
  8.             System.out.println("#"+Thread.currentThread().getName()+" : "+ count--);  
  9.         }  
  10.         System.out.println("#"+Thread.currentThread().getName()+" : exiting "+ count--);  
  11.     }  
  12.     public static void main(String[] args)  
  13.     {  
  14.         ThreadFromRunnable tr = new ThreadFromRunnable();  
  15.         Thread thread = new Thread(tr);  
  16.         Thread thread2 = new Thread(tr);  
  17.         thread.start();  
  18.         thread2.start();  
  19.     }  
  20. }  

output:

#Thread-0 got count from 10

#Thread-1 got count from 10

#Thread-1 : 10

#Thread-1 : 9

#Thread-1 : 8

#Thread-1 : 7

#Thread-1 : 6

#Thread-1 : 5

#Thread-1 : 4

#Thread-0 : 10

#Thread-1 : 3

#Thread-0 : 9

#Thread-1 : 2

#Thread-0 : 8

#Thread-1 : 1

#Thread-0 : 7

#Thread-1 : exiting 0

#Thread-0 : 6

#Thread-0 : 5

#Thread-0 : 4

#Thread-0 : 3

#Thread-0 : 2

#Thread-0 : 1

#Thread-0 : exiting 0

2、通過繼承Thread類建立線程

(1).首先定義一個類去繼承Thread父類,重寫父類中的run()方法。在run()方法中加入具體的任務代碼或處理邏輯。

(2).直接建立一個ThreadDemo2類的對象,也可以利用多态性,變量聲明為父類的類型。

(3).調用start方法,線程t啟動,隐含的調用run()方法。

[java]  view plain copy

  1. public class ThreadExtendsThread extends Thread {  
  2.     //static int count =10;  
  3.     public void run()  
  4.     {  
  5.         int count =10;  
  6.         System.out.println("\t#"+Thread.currentThread().getName()+" got count from " + count);  
  7.         while(count > 0)  
  8.         {  
  9.             System.out.println("{1}quot;+this.getName()+" : "+count--);  
  10.         }  
  11.         System.out.println("{1}quot;+this.getName()+" : existing count=" + count);  
  12.     }  
  13.     public static void main(String[] args)  
  14.     {  
  15.         ThreadExtendsThread thread = new ThreadExtendsThread();  
  16.         ThreadExtendsThread thread2 = new ThreadExtendsThread();  
  17.         thread.start();  
  18.         thread2.start();  
  19.     }  
  20. }  

output:

#Thread-0 got count from 10

#Thread-1 got count from 10

$Thread-1 : 10

$Thread-1 : 9

$Thread-1 : 8

$Thread-1 : 7

$Thread-1 : 6

$Thread-1 : 5

$Thread-1 : 4

$Thread-1 : 3

$Thread-1 : 2

$Thread-1 : 1

$Thread-0 : 10

$Thread-1 : existing count=0

$Thread-0 : 9

$Thread-0 : 8

$Thread-0 : 7

$Thread-0 : 6

$Thread-0 : 5

$Thread-0 : 4

$Thread-0 : 3

$Thread-0 : 2

$Thread-0 : 1

$Thread-0 : existing count=0

3、兩種方式的比較

首先分析兩種方式的輸出結果,同樣是建立了兩個線程,為什麼結果不一樣呢?

使用實作Runnable接口方式建立線程可以共享同一個目标對象(TreadDemo1 tt=new TreadDemo1();),實作了多個相同線程處理同一份資源。

然後再看一段來自JDK的解釋:

The 

Runnable

 interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called

run

.

This interface is designed to provide a common protocol for objects that wish to execute code while they are active. For example,

Runnable

 is implemented by class

Thread

. Being active simply means that a thread has been started and has not yet been stopped.

In addition, 

Runnable

 provides the means for a class to be active while not subclassing

Thread

. A class that implements

Runnable

 can run without subclassing

Thread

 by instantiating a

Thread

 instance and passing itself in as the target. In most cases, the

Runnable

 interface should be used if you are only planning to override the

run()

 method and no other

Thread

 methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.

采用繼承Thread類方式:

(1)優點:編寫簡單,如果需要通路目前線程,無需使用Thread.currentThread()方法,直接使用this,即可獲得目前線程。

(2)缺點:因為線程類已經繼承了Thread類,是以不能再繼承其他的父類。

采用實作Runnable接口方式:

(1)優點:線程類隻是實作了Runable接口,還可以繼承其他的類。在這種方式下,可以多個線程共享同一個目标對象,是以非常适合多個相同線程來處理同一份資源的情況,進而可以将CPU代碼和資料分開,形成清晰的模型,較好地展現了面向對象的思想。

(2)缺點:程式設計稍微複雜,如果需要通路目前線程,必須使用Thread.currentThread()方法。

注意:(android為例)在代碼中如果線程中有使用死循環,一定要在Acticity onCreate()時 start()線程,在onDestroy()時使用interrupt()方法把線程關閉,并把線程設定為null。