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


實現並啟動線程有兩種方法
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM