日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java线程的6种状态

發(fā)布時(shí)間:2023/12/4 java 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java线程的6种状态 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

線程的概念,以及線程的創(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)的方式:

  • 調(diào)用線程的start()方法
  • 當(dāng)前線程sleep()方法結(jié)束
  • 其他線程join()結(jié)束
  • 等待用戶輸入完畢(阻塞式IO,拿到IO結(jié)果后)
  • 當(dāng)前線程拿到所需鎖
  • 當(dāng)前線程時(shí)間片耗盡
  • 調(diào)用當(dāng)前線程的yield()方法
  • 運(yùn)行中狀態(tài)Running
    獲得CPU運(yùn)行時(shí)間后,運(yùn)行中的狀態(tài)

    進(jìn)入Running狀態(tài)的方式(唯一):

  • 操作系統(tǒng)的線程調(diào)度程序,從可運(yùn)行狀態(tài)的線程池中,選出當(dāng)前線程去執(zhí)行;
  • 阻塞狀態(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)的方式:

  • 當(dāng)前線程調(diào)用sleep()方法
  • 當(dāng)前線程執(zhí)行過程中,調(diào)用了其他線程的join()方法,當(dāng)前線程進(jìn)入阻塞狀態(tài)
  • 等待阻塞式IO時(shí)
  • 死亡狀態(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))

  • 線程睡眠會(huì)交出CPU,讓給其他線/進(jìn)程執(zhí)行
  • sleep()方法不會(huì)釋放鎖,即當(dāng)前線程持有某個(gè)對(duì)象鎖時(shí),即使調(diào)用sleep()方法其他線程也無法訪問這個(gè)對(duì)象。
  • 調(diào)用sleep(),當(dāng)前線程從Running到blocked,sleep結(jié)束,從blocked到Runnable
  • public static native void sleep(long millis) throws InterruptedException;

    線程讓步:yield()方法

    線程讓步,指的是讓當(dāng)前線程暫停執(zhí)行,并執(zhí)行其他線程
    與sleep()的區(qū)別在于

  • yield()方法無法控制具體交出CPU的時(shí)間
  • yield()方法只能讓擁有相同優(yōu)先級(jí)的線程獲得CPU執(zhí)行的機(jī)會(huì)
  • yield()方法讓當(dāng)前線程進(jìn)入Runnable狀態(tài)
  • 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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。