java Thread的start和run方法的区别
一、認識Thread的 start() 和 run()
概述:
t.start()會導(dǎo)致run()方法被調(diào)用,run()方法中的內(nèi)容稱為線程體,它就是這個線程需要執(zhí)行的工作。
用start()來啟動線程,實現(xiàn)了真正意義上的啟動線程,此時會出現(xiàn)異步執(zhí)行的效果,即在線程的創(chuàng)建和啟動中所述的隨機性。
而如果使用run()來啟動線程,就不是異步執(zhí)行了,而是同步執(zhí)行,不會達到使用線程的意義
1.start():
我們先來看看API中對于該方法的介紹:
“Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.”?
“start()方法會使得該線程開始執(zhí)行;java虛擬機會去調(diào)用該線程的run()方法?!?/p>
???? 使該線程開始執(zhí)行;Java 虛擬機調(diào)用該線程的?run?方法。
???? 結(jié)果是兩個線程并發(fā)地運行;當(dāng)前線程(從調(diào)用返回給?start?方法)和另一個線程(執(zhí)行其?run?方法)。
???? 多次啟動一個線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動。
用start方法來啟動線程,真正實現(xiàn)了多線程運行,這時無需等待run方法體代碼執(zhí)行完畢而直接繼續(xù)執(zhí)行下面的代碼。通過調(diào)
用Thread類的 start()方法來啟動一個線程,這時此線程處于就緒(可運行)狀態(tài),并沒有運行,一旦得到cpu時間片,就開始
執(zhí)行run()方法,這里方法 run()稱為線程體,它包含了要執(zhí)行的這個線程的內(nèi)容,Run方法運行結(jié)束,此線程隨即終止。
?
2.run():
public class Thread extends Object implements Runnable我們還是先看看API中對該方法的介紹:
????? 如果該線程是使用獨立的?Runnable?運行對象構(gòu)造的,則調(diào)用該?Runnable?對象的?run?方法;否則,該方法不執(zhí)行任何操作并返回。
??? Thread?的子類應(yīng)該重寫該方法。
run()方法只是類的一個普通方法而已,如果直接調(diào)用Run方法,程序中依然只有主線程這一個線程,其程序執(zhí)行路徑還是只有
一條,還是要順序執(zhí)行,還是要等待run方法體執(zhí)行完畢后才可繼續(xù)執(zhí)行下面的代碼,這樣就沒有達到寫線程的目的。
?
3.總結(jié)
調(diào)用start方法方可啟動線程,而run方法只是thread的一個普通方法調(diào)用,還是在主線程里執(zhí)行。
二、代碼實例:
?通過start啟動線程,異步啟動
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");}輸出結(jié)果: pingpong
?
通過run啟動線程,同步啟動
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");}輸出結(jié)果:pongping
?
通過以上兩個程序?qū)嵗?#xff0c;可以很容易的區(qū)分出start()方法和run()方法的區(qū)別:
t.start(); 該行代碼相當(dāng)于是啟動線程,異步操作
t.run(); 該行代碼相當(dāng)于是使用t這個類中的run方法而已,只是主線程的一個普通的方法
三、線程狀態(tài)說明:
線程狀態(tài)從大的方面來說,可歸結(jié)為:初始狀態(tài)、可運行狀態(tài)、不可運行狀態(tài)和消亡狀態(tài),說明如下:
1)線程的實現(xiàn)有兩種方式,一是繼承Thread類,二是實現(xiàn)Runnable接口,但不管怎樣,當(dāng)我們new了thread實例后,線程就進入了初始狀態(tài);
2)當(dāng)該對象調(diào)用了start()方法,就進入可運行狀態(tài);
3)進入可運行狀態(tài)后,當(dāng)該對象被操作系統(tǒng)選中,獲得CPU時間片就會進入運行狀態(tài);
4)進入運行狀態(tài)后情況就比較多,大致有如下情形:
? ? ? ?a.?run()方法或main()方法結(jié)束后,線程就進入終止?fàn)顟B(tài);
? ? ? ?b. 當(dāng)線程調(diào)用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(tài)(該狀態(tài)既停止當(dāng)前線程,但并不釋放
所占有的資源)。當(dāng)sleep()結(jié)束或join()結(jié)束后,該線程進入可運行狀態(tài),繼續(xù)等待OS分配時間片; 當(dāng)線程剛進入可運行
狀態(tài)(注意,還沒運行),發(fā)現(xiàn)將要調(diào)用的資源被鎖牢(synchroniza,lock),將會立即進入鎖池狀態(tài),等待獲取鎖標(biāo)記(這時
的鎖池里也許已經(jīng)有了其他線程在等待獲取鎖標(biāo)記,這時它們處于隊列狀態(tài),既先到先得),一旦線程獲得鎖標(biāo)記后,就
轉(zhuǎn)入可運行狀態(tài),等待OS分配 CPU時間片;
? ? ? ? c. 當(dāng)線程調(diào)用wait()方法后會進入等待隊列(進入這個狀態(tài)會釋放所占有的所有資源,與阻塞狀態(tài)不同),進入這個狀
態(tài)后,是不能自動喚醒的,必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒(由于notify()只是喚醒一個線程,
但我們由不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用
notifyAll()方法,喚醒有所線程),線程被喚醒后會進入鎖池,等待獲取鎖標(biāo)記。 當(dāng)線程調(diào)用stop方法,即可使線程進入消
亡狀態(tài),但是由于stop方法是不安全的,不鼓勵使用,大家可以通過run方法里的條件變通實現(xiàn)線程的 stop。
總結(jié)
以上是生活随笔為你收集整理的java Thread的start和run方法的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java.lang.RuntimeExc
- 下一篇: 最优服务次序问题 和 汽车加油问题