天天看点

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。