認識多線程中start和run方法的區別?


一、認識多線程中的 start() 和 run()

1。start():

    先來看看Java API中對於該方法的介紹:

     使該線程開始執行;Java 虛擬機調用該線程的 run 方法。

     結果是兩個線程並發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。

     多次啟動一個線程是非法的。特別是當線程已經結束執行后,不能再重新啟動。

用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體中的代碼執行完畢而直接繼續執行后續的代碼。通過調用Thread類的 start()方法來啟動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這里的run()方法 稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。

2。run():

同樣先看看Java API中對該方法的介紹:

      如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作並返回。

    Thread 的子類應該重寫該方法。

run()方法只是類的一個普通方法而已,如果直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是只有一條,還是要順序執行,還是要等待run方法體執行完畢后才可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。

3。總結:

調用start方法方可啟動線程,而run方法只是thread類中的一個普通方法調用,還是在主線程里執行。

二、代碼實例:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
public  static  void  main(String args[]) {
         Thread t = new  Thread() {
             public  void  run() {
                 pong();
             }
         };
         t.start();
         System.out.print( "ping" );
     }
 
     static  void  pong() {
         System.out.print( "pang" );
     }

輸出結果: pingpang

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
public  static  void  main(String args[]) {
         Thread t = new  Thread() {
             public  void  run() {
                 pong();
             }
         };
         t.run();
         System.out.print( "ping" );
     }
 
     static  void  pong() {
         System.out.print( "pang" );
     }

輸出結果:pongpang

 

通過以上兩個程序實例,可以很容易的區分出start()方法和run()方法的區別:

t.start(); 該行代碼相當於是啟動線程,

t.run(); 該行代碼相當於是使用t這個類中的run方法而已.

三、線程狀態說明:

線程狀態從大的方面來說,可歸結為:初始狀態可運行狀態不可運行狀態消亡狀態,具體可細分為上圖所示7個狀態,說明如下:

1)線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable接口,但不管怎樣,當我們new了Thread實例后,線程就進入了初始狀態

2)當該對象調用了start()方法,就進入可運行狀態

3)進入可運行狀態后,當該對象被操作系統選中,獲得CPU時間片就會進入運行狀態

4)進入運行狀態后涉及的情況就比較多,大致有如下情形: ﹒run()方法或main()方法結束后,線程就進入終止狀態; 當線程調用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(該狀態雖停止當前線程,但並不釋放所占有的資源)。當sleep()結束或join()結束后,該線程進入可運行狀態,繼續等待OS分配時間片; 當線程剛進入可運行狀態(注意,還沒運行),發現將要調用的資源被鎖住(synchroniza,lock),將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池里也許已經有了其他線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記后,就轉入可運行狀態,等待OS分配 CPU時間片; 當線程調用wait()方法后會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態后,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由於不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒后會進入鎖池,等待獲取鎖標記。 當線程調用stop方法,即可使線程進入消亡狀態,但是由於stop方法是不安全的,不鼓勵使用,大家可以通過run方法里的條件變通實現線程的 stop。

 

安全終止線程的自定義方法:

public class SafeStopThread implements Runnable{

   //定義線程終止的開關
  private volatile boolean stop=false;//此變量必須加上volatile
  int a=0;
  @Override
  public void run() {
    // TODO Auto-generated method stub
    while(!stop){
      synchronized ("") {
      a++;
      try {
        Thread.sleep(100);
      } catch (Exception e) {
        // TODO: handle exception
      }
      a--;
      String tn=Thread.currentThread().getName();
      System.out.println(tn+":a="+a);

    }
   }
  //線程終止方法
   public void threadStop(){
      stop=true;
   }
   public static void main(String[] args) {
       SafeStopThread t=new SafeStopThread();
       Thread t1=new Thread(t);
       t1.start();
       for(int i=0;i<5;i++){
           new Thread(t).start();
       }
       t.threadStop();//改變終止線程的狀態
   }

 }

線程安全終止:https://blog.csdn.net/lexang1/article/details/49819347

好文轉載學習自:https://www.cnblogs.com/whyalwaysme/p/4495959.html


免責聲明!

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



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