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