Java线程的6种状态
線程的概念,以及線程的創(chuàng)建方式,見我之前寫的博文
本篇文章主要講Java線程的6種狀態(tài)
6種狀態(tài):初始狀態(tài)(new) 、可運(yùn)行狀態(tài)(Runnable)、運(yùn)行狀態(tài)(Running)、阻塞狀態(tài)(Blocked)、死亡狀態(tài)(Dead)、等待隊(duì)列
初始狀態(tài)(New):
進(jìn)程剛創(chuàng)建,未調(diào)用new Thread().start()方法時(shí)的狀態(tài),進(jìn)程創(chuàng)建方式
可運(yùn)行狀態(tài)(Runnable):
在創(chuàng)建線程并調(diào)用start()方法之后,獲得CPU運(yùn)行時(shí)間之前的狀態(tài)
進(jìn)入Runnable狀態(tài)的方式:
運(yùn)行中狀態(tài)Running
獲得CPU運(yùn)行時(shí)間后,運(yùn)行中的狀態(tài)
進(jìn)入Running狀態(tài)的方式(唯一):
阻塞狀態(tài)Blocked
運(yùn)行中的線程,可以會(huì)由于各種原因進(jìn)入到阻塞狀態(tài)。如調(diào)用sleep()方法讓線程睡眠,調(diào)用wait()方法讓線程等待,調(diào)用join()、suspend()方法(已棄用)或者阻塞式IO。
進(jìn)入阻塞狀態(tài)的方式:
死亡狀態(tài)Dead
無論是正常退出(run()方法執(zhí)行完畢),還是拋出了未捕獲的異常,都會(huì)導(dǎo)致線程進(jìn)入Dead狀態(tài)。
或者是主線程main方法執(zhí)行完畢
在一個(gè)死去的線程上調(diào)用start()方法,會(huì)拋出java.lang.IllegalThreadStateException異常
線程的狀態(tài)流轉(zhuǎn)圖
線程睡眠:sleep()方法
線程睡眠,指的是讓當(dāng)前線程暫停執(zhí)行,等到指定時(shí)間后再恢復(fù)執(zhí)行(Runnable狀態(tài))
線程讓步:yield()方法
線程讓步,指的是讓當(dāng)前線程暫停執(zhí)行,并執(zhí)行其他線程
與sleep()的區(qū)別在于
yield()方法:
public static native void yield();等待線程終止:join()方法
等待線程終止,指的是:主線程中調(diào)用該方法,就會(huì)讓調(diào)用該方法的線程先執(zhí)行,等執(zhí)行結(jié)束后,再回到主線程繼續(xù)執(zhí)行。(即等待,調(diào)用join()方法的線程執(zhí)行完畢后,再執(zhí)行)
join()方法:
public final void join() throws InterruptedException {//join帶參數(shù)指的是等待的超時(shí)時(shí)間,為0代表永久等待join(0);}wait()方法
obj.wait(),當(dāng)前線程調(diào)用對(duì)象的wait()方法,當(dāng)前線程釋放對(duì)象鎖,進(jìn)入等待隊(duì)列。依靠notify()/notifyAll()喚醒或者wait(long timeout)timeout時(shí)間到自動(dòng)喚醒
public final void wait() throws InterruptedException {}public final native void wait(long timeout) throws InterruptedException;notify()方法
obj.notify()喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程,選擇是任意性的。notifyAll()喚醒在此對(duì)象監(jiān)視器上等待的所有線程
public final native void notify();public final native void notifyAll();線程停止的3種方式
1):設(shè)置標(biāo)志位,讓線程正常停止
class MyThread1 extends Thread {private boolean flag = false;@Overridepublic void run() {int i=0;while (!flag) {System.out.println("線程循環(huán)執(zhí)行次數(shù):"+i);}} }2):使用stop方法強(qiáng)制線程停止,不安全,已廢棄!
stop方法:
@Deprecatedpublic final void stop() {}為什么stop()不安全?
因?yàn)閟top()會(huì)解除相應(yīng)線程持有的所有鎖,并且當(dāng)在線程對(duì)象上執(zhí)行stop方法時(shí),會(huì)立即停止該線程
比如當(dāng)正在執(zhí)行如下同步方法時(shí),執(zhí)行到x=10,線程調(diào)用了stop()方法,那就會(huì)進(jìn)入不一致的狀態(tài),所以線程不安全
public synchronized void f() {x =10;y =20; }3):調(diào)用interrupt()方法
調(diào)用Thread類的interrupted()方法,其本質(zhì)只是設(shè)置該線程的中斷標(biāo)志,將中斷標(biāo)志設(shè)置為true,并根據(jù)線程狀態(tài)決定是否拋出異常。因此,通過interrupted()方法真正實(shí)現(xiàn)線程的中斷原理是 :開發(fā)人員根據(jù)中斷標(biāo)志的具體值來決定如何退出線程。
interrupt()方法
public void interrupt() {}拓展:
為什么notify(), wait()等函數(shù)定義在Object中,而不是Thread中
Object中的wait(), notify()等函數(shù),和synchronized一樣,會(huì)對(duì)“對(duì)象的同步鎖”進(jìn)行操作。
wait()會(huì)使“當(dāng)前線程”等待,因?yàn)榫€程進(jìn)入等待狀態(tài),所以線程應(yīng)該釋放它鎖持有的“同步鎖”,否則其它線程獲取不到該“同步鎖”而無法運(yùn)行!
OK,線程調(diào)用wait()之后,會(huì)釋放它鎖持有的“同步鎖”;而且,根據(jù)前面的介紹,我們知道:等待線程可以被notify()或notifyAll()喚醒。現(xiàn)在,請(qǐng)思考一個(gè)問題:notify()是依據(jù)什么喚醒等待線程的?或者說,wait()等待線程和notify()之間是通過什么關(guān)聯(lián)起來的?答案是:依據(jù)“對(duì)象的同步鎖”。
負(fù)責(zé)喚醒等待線程的那個(gè)線程(我們稱為“喚醒線程”),它只有在獲取“該對(duì)象的同步鎖”(這里的同步鎖必須和等待線程的同步鎖是同一個(gè)),并且調(diào)用notify()或notifyAll()方法之后,才能喚醒等待線程。雖然,等待線程被喚醒;但是,它不能立刻執(zhí)行,因?yàn)閱拘丫€程還持有“該對(duì)象的同步鎖”。必須等到喚醒線程釋放了“對(duì)象的同步鎖”之后,等待線程才能獲取到“對(duì)象的同步鎖”進(jìn)而繼續(xù)運(yùn)行。
總之,notify(), wait()依賴于“同步鎖”,而“同步鎖”是對(duì)象鎖持有,并且每個(gè)對(duì)象有且僅有一個(gè)!這就是為什么notify(), wait()等函數(shù)定義在Object類,而不是Thread類中的原因。
總結(jié)
以上是生活随笔為你收集整理的Java线程的6种状态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dnf搬砖代码Python_DNF:95
- 下一篇: Java线程的优先级