標籤:
一、認識Thread的 start() 和 run()
1。start():
我們先來看看API中對於該方法的介紹:
使該線程開始執行;JAVA 虛擬機器調用該線程的 run 方法。
結果是兩個線程並發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。
多次啟動一個線程是非法的。特別是當線程已經結束執行後,不能再重新啟動。
用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的 start()方法來啟動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這裡方法 run()稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。
2。run():
我們還是先看看API中對該方法的介紹:
如果該線程是使用獨立的 Runnable 運行物件建構的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作並返回。
Thread 的子類應該重寫該方法。
run()方法只是類的一個普通方法而已,如果直接調用Run方法,程式中依然只有主線程這一個線程,其程式執行路徑還是只有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。
3。總結:
調用start方法方可啟動線程,而run方法只是thread的一個普通方法調用,還是在主線程裡執行。
二、代碼執行個體:
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("pong");}
輸出結果: pingpong
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("pong");}
輸出結果:pongping
通過以上兩個程式執行個體,可以很容易的區分出start()方法和run()方法的區別:
t.start(); 該行代碼相當於是啟動線程,
t.run(); 該行代碼相當於是使用t這個類中的run方法而已.
三、線程狀態說明:
線程狀態從大的方面來說,可歸結為:初始狀態、可運行狀態、不可運行狀態和消亡狀態,具體可細分為所示7個狀態,說明如下:
1)線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable介面,但不管怎樣,當我們new了thread執行個體後,線程就進入了初始狀態;
2)當該對象調用了start()方法,就進入可運行狀態;
3)進入可運行狀態後,當該對象被作業系統選中,獲得CPU時間片就會進入運行狀態;
4)進入運行狀態後case就比較多,大致有如下情形: ﹒run()方法或main()方法結束後,線程就進入終止狀態; 當線程調用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(該狀態既停 止當前線程,但並不釋放所佔有的資源)。當
sleep()結束或join()結束後,該線程進入可運行狀態,繼續等待OS分配時間片; 當線程剛進入可運行狀態(注意,還沒運行),發現將要調用的資源被鎖牢(synchroniza,lock),將會立即進入鎖池狀態,等待擷取鎖標記(這時的鎖池裡也許已經有了其他線
程在等待擷取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記後,就轉入可運行狀態,等待OS分配 CPU時間片; 當線程調用wait()方法後會進入等待隊列(進入這個狀態會釋放所佔有的所有資源,與阻塞狀態不同),進入這個狀態後,
是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒
有所線程),線程被喚醒後會進入鎖池,等待擷取鎖標記。 當線程調用stop方法,即可使線程進入消亡狀態,但是由於stop方法是不安全的,不鼓勵使用,大家可以通過run方法裡的條件變通實現線程的 stop。
Java -- Thread中start和run方法的區別