1. 程式人生 > >線程的啟動的兩種方法,Runnable接口,run()的調用

線程的啟動的兩種方法,Runnable接口,run()的調用

ride 之前 線程終止 源碼解析 star 有意 tro thread類 override

實現並啟動線程有兩種方法
1、寫一個類繼承自Thread類,重寫run方法。用start方法啟動線程
2、寫一個類實現Runnable接口,實現run方法。用new Thread(Runnable target).start()方法來啟動

多線程原理:相當於玩遊戲機,只有一個遊戲機(cpu),可是有很多人要玩,於是,start是排隊!等CPU選中你就是輪到你,你就run(),當CPU的運行的時間片執行完,這個線程就繼續排隊,等待下一次的run()。

調用start()後,線程會被放到等待隊列,等待CPU調度,並不一定要馬上開始執行,只是將這個線程置於可動行狀態。然後通過JVM,線程Thread會調用run()方法,執行本線程的線程體。先調用start後調用run,這麽麻煩,為了不直接調用run?

就是為了實現多線程的優點,沒這個start不行。

1.start()方法來啟動線程,真正實現了多線程運行。這時無需等待run方法體代碼執行完畢,可以直接繼續執行下面的代碼;通過調用Thread類的start()方法來啟動一個線程, 這時此線程是處於就緒狀態, 並沒有運行。 然後通過此Thread類調用方法run()來完成其運行操作的, 這裏方法run()稱為線程體,它包含了要執行的這個線程的內容, Run方法運行結束, 此線程終止。然後CPU再調度其它線程。
2.run()方法當作普通方法的方式調用。程序還是要順序執行,要等待run方法體執行完畢後,才可繼續執行下面的代碼; 程序中只有主線程——這一個線程, 其程序執行路徑還是只有一條, 這樣就沒有達到寫線程的目的。

記住:多線程就是分時利用CPU,宏觀上讓所有線程一起執行 ,也叫並發

 1 public class Test {  
 2     public static void main(String[] args) {  
 3         Runner1 runner1 = new Runner1();  
 4         Runner2 runner2 = new Runner2();  
 5 //      Thread(Runnable target) 分配新的 Thread 對象。  
 6         Thread thread1 = new Thread(runner1);  
7 Thread thread2 = new Thread(runner2); 8 // thread1.start(); 9 // thread2.start(); 10 thread1.run(); 11 thread2.run(); 12 } 13 } 14 15 class Runner1 implements Runnable { // 實現了Runnable接口,jdk就知道這個類是一個線程 16 public void run() { 17 for (int i = 0; i < 100; i++) { 18 System.out.println("進入Runner1運行狀態——————————" + i); 19 } 20 } 21 } 22 23 class Runner2 implements Runnable { // 實現了Runnable接口,jdk就知道這個類是一個線程 24 public void run() { 25 for (int i = 0; i < 100; i++) { 26 System.out.println("進入Runner2運行狀態==========" + i); 27 } 28 } 29 }

以上整理來自:http://blog.csdn.net/xuxurui007/article/details/7685076

【線程的創建和啟動的步驟實現Runnable接口方式)】

1.定義Runnable接口的實現類,並重寫其中的run方法。run()方法的方法體線程執行體

class SonThread implement Runnable{

  public void run(){

  ......

  }

 }

2.創建Runnable接口實現類的實例。 sonThread s1=new SonThread();

3.用該實例作為Thread的target來創建Thread對象。 Thread t1 =new Thread(s1);

4.調用該對象的start()方法啟動線程。 t1.start();

【註意一:關於命名】

在創建Thread 對象的時候可以為該Thread對象指定一個名字

技術分享

【註意二:Thread的構造方法】

Runnable對象作為Thread對象的target,Runnable實現類裏面包含run方法僅僅作為執行體。也就是說Thread類的作用是把run方法包裝成線程的執行體。

實際運行的線程對象依然是Thread實例,只是該Thread線程負責執行其target的run方法。

 1 //1.1定義Runnable接口的實現類
 2 class SecondThread implements Runnable{
 3 
 4     //1.2重寫其中的run方法
 5     @Override
 6     public void run() {
 7         for(int i=0;i<10;i++){
 8             System.out.println(Thread.currentThread().getName()+"===="+i);
 9         }
10     }
11     
12 }
13 public class Demo2 {
14     
15     public static void main(String[] args) {
16         //2.創建Runnable的接口實現類的實例
17         SecondThread s1=new SecondThread();
18         SecondThread s2=new SecondThread();
19         //2.用Runnable的接口實現類的實例作為Thread的target,創建Thread對象
20         Thread t1=new Thread(s1);
21         Thread t2=new Thread(s2,"Higgin");  //創建Thread對象的同時可以為之命名
22         
23         //啟動線程
24         t1.start();
25         t2.start();
26         
27         for(int i=0;i<10;i++){
28             System.out.println(Thread.currentThread().getName()+"===="+i);
29         }
30     }
31 }

以上整理來自:http://www.cnblogs.com/HigginCui/p/5901593.html

通過JDK源碼解析Thread(Runable target ...)調用的是哪個run方法

代碼1:

 1 new Thread(new Runnable() {  
 2     @Override  
 3     public void run() {  
 4         System.out.println("Run of Runnable");  
 5     }  
 6 }) {  
 7     public void run() {  
 8         System.out.println("Run of Thread");  
 9     }  
10 }.start();  

代碼2:

 1 new Thread(new Runnable() {  
 2     @Override  
 3     public void run() {  
 4         System.out.println("Run of Runnable");  
 5     }  
 6 }) {  
 7     public void run() {  
 8         System.out.println("Run of Thread");  
 9         super.run();  
10     }  
11 }.start();  

首先,我們來看一下JDK的Thread源碼,片段 3 如下:

1 private Runnable target;  
public void run() {  
    if (target != null) {  
        target.run();  
    }  
}  

在run()方法中,首先會檢查target是否為空,如果不是,則執行該target的run()方法。

那麽,對於上面兩段代碼的執行,也就清楚了。

在第一個代碼段 1 中,重寫了Thread的run()方法,同時傳入了一個Runnable對象,該對象也實現了run()方法。該Thread對象調用start()方法後,會執行該對象重寫的run()方法,其輸出結果也就是Run of Thread,輸出完後,run()方法返回,該線程對象的生命周期也就結束了。

在第二個代碼段 2 中,同樣也重寫了Thread的run()方法,同時傳入了一個Runnable對象,實現了run()方法。唯一不同的是,在Thread重寫的run方法中,在打印輸出後,還執行了super.run(),這就有意思了。

首先,該線程啟動運行後,執行其重寫的run()方法,輸出Run of Thread。

接下來調用super.run(),也就是調用超類的run()方法,而該超類的run()方法,也就是JDK定義的Thread類的run(),其執行如上代碼段 3 所示;顯然target不為空,這時候會調用該對象的run()方法,會輸出Run of Runnable.。

如果,上面的Thread並未重寫run()方法,那麽,執行的結果還是一樣。首先會執行該Thread的run()方法,因為此時並未重寫該方法,所以還是會調用JDK定以的run()方法,也就是上面的代碼段 3,在該代碼段中會判斷target是否為空,顯然不是,所以會調用Runnable對象實現的run()方法。

總結:對於Thread(Runnable target ...),不管傳入的Target是否為空,首先都會執行Thread自己的run()方法。如果重寫了該方法且該方法中沒有super.run(),那麽是永遠不會調用Runnable實現的run()方法;如果沒有重寫該方法,則會去判斷target是否為空,以此來決定調用target實現的run()方法;如果重寫了該方法,且該方法中有super.run(),在執行完該語句之前的所有代碼後,會判斷target是否為空,以此來決定調用target實現的run()方法,執行完後,接著執行該語句之後的代碼。

以上整理來自:http://blog.csdn.net/guguituzi/article/details/44593863

線程的啟動的兩種方法,Runnable接口,run()的調用