最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解Java線程的6種狀態(tài)與生命周期

 更新時間:2022年05月10日 16:32:56   作者:淵渟岳  
一個線程在給定的時間點只能處于一種狀態(tài)。線程可以有6種狀態(tài):New、Runnable、Blocked、Waiting、Timed?waiting和Terminated。本文將詳細講解這6種狀態(tài),需要的可以參考一下

1.線程狀態(tài)(生命周期)

一個線程在給定的時間點只能處于一種狀態(tài)。

線程可以有如下6 種狀態(tài):

  • New (新創(chuàng)建):未啟動的線程;
  • Runnable (可運行):可運行的線程,需要等待操作系統(tǒng)資源;
  • Blocked (被阻塞):等待監(jiān)視器鎖而被阻塞的線程;
  • Waiting (等待):等待喚醒狀態(tài),無限期地等待另一個線程喚醒;
  • Timed waiting (計時等待):在指定的等待時間內等待另一個線程執(zhí)行操作的線程;
  • Terminated (被終止):已退出的線程。

要確定一個線程的當前狀態(tài), 可調用getState 方法

線程狀態(tài)關系圖

注意:虛線框(全大寫英文)的狀態(tài)為Java線程狀態(tài)。

圖片

2.操作線程狀態(tài)

2.1.新創(chuàng)建狀態(tài)(NEW)

就是實例化線程完成后,未啟動線程的狀態(tài)。

可通過三種方式創(chuàng)建線程

  • 重寫Thread類run()方法
  • 實現Runnable接口
  • 實現Callable接口

一個簡單的例子概括三種方式

public?class?Demo?{

????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????/**
?????????*?1.直接重寫run()?或繼承Thread類再重寫run()
?????????*/
????????Thread?thread?=?new?Thread()?{
????????????@Override
????????????public?void?run()?{
????????????????System.out.println("Thread");
????????????}
????????};
????????//?開啟線程
????????thread.start();

????????/**
?????????*?2.lambda、內部類或線程類方式實現Runnable接口,實現run()方法
?????????*?再交給Thread?類
?????????*/
????????Thread?runThread?=?new?Thread(()?->?{
????????????System.out.println("Runnable");
????????});
????????//?開啟線程
????????runThread.start();

????????/**
?????????*?3.lambda、內部類或線程類方式實現Callable接口,實現call()方法
?????????*?再交給Thread 類:FutureTask本質也是Runnable實現類
?????????*/
????????FutureTask<String>?futureTask?=?new?FutureTask<String>(()?->?{
????????????System.out.println("Callable");
????????????return?"CallableThread";
????????});
????????Thread?callThread?=?new?Thread(futureTask);
????????//?開啟線程
????????callThread.start();
????????//?獲取call()方法的返回值
????????String?s?=?futureTask.get();
????????System.out.println("call()方法的返回值:"+s);
????}

}

不重寫 run() 或 call() 方法直接實例化Thread類創(chuàng)建的線程沒有實際意義;

只有Callable方式創(chuàng)建的線程可以獲取線程的返回值。

2.2.可運行狀態(tài)(RUNNABLE)

該狀態(tài)指的是線程實例化對象調用start()方法后進入的狀態(tài)。線程處于可以運行狀態(tài),如果有處理器等資源,就可以執(zhí)行程序。

該狀態(tài)在操作系統(tǒng)層面包含兩步:線程就緒和線程運行中,但在Java線程狀態(tài)中,這兩步都統(tǒng)稱為Runnable(可運行)狀態(tài)。

線程由就緒狀態(tài)變?yōu)檫\行狀態(tài),重點就看你的線程有沒有搶到CPU資源(CPU時間片),誰搶到就運行,沒搶到就等。因為CPU時間片(執(zhí)行時間)非常短,大概十幾毫秒,所以線程切換的這個時間是非常短的,就緒狀態(tài)變?yōu)檫\行狀態(tài)的時間也非常短,在開發(fā)時幾乎感覺不到這種狀態(tài)的變化,所以在Java中將兩者看作是一個整體,重點關注線程可否運行并區(qū)別于其他狀態(tài)即可,更進一步簡化線程的開發(fā)。如果你的程序要運行很久(比如寫個死循環(huán)),在一個CPU時間片內沒有執(zhí)行完成,那么你的線程就要搶下一次的CPU時間片,搶到了才可以繼續(xù)執(zhí)行程序,沒搶到那就要繼續(xù)搶,直到線程中的程序執(zhí)行完成。

其實這個場景應該都見到過,例如多個線程執(zhí)行同一個程序,都將日志打印到同一個文件時,就會出現不同線程的日志混在了一起的情況,不利于排查問題。解決這種問題常見的方法有:一是分線程打印日志到不同文件;二是將日志信息保存到字符串對象中,在程序的最后將日志信息一次性打印到文件。第二種方式就是利用CPU的一個時間片來完成日志信息的打印。

注意:程序只能對新建狀態(tài)的線程調用start()方法,不要對處于非新建狀態(tài)的線程調用start() 方法,這都會引發(fā)IllegalThreadStateException異常。

2.3.被阻塞狀態(tài)(BLOCKED)

線程處于等待監(jiān)視器而被阻塞的狀態(tài)。有一個線程獲取了鎖未釋放,其他線程也來獲取,但發(fā)現獲取不到鎖也進入了被阻塞狀態(tài)。

被阻塞狀態(tài)只存在于多線程并發(fā)訪問下,區(qū)別于后面兩種因線程自己進入”等待“而導致的阻塞。

進入狀態(tài)

  • 進入synchronized 代碼塊/方法
  • 未獲取到鎖

退出狀態(tài)

  • 獲取到監(jiān)視器鎖

2.4.等待喚醒狀態(tài)(WAITING)

整個流程是這樣的:線程在某個對象的同步方法中先獲取到對象鎖;在執(zhí)行wait方法時,該線程將釋放對象鎖,并且該線程被放入到這個對象的等待隊列;等待另一個線程獲取到同一個對象的鎖,然后通過notify() 或 notifyAll() 方法喚醒對象等待隊列中的線程。

從整個流程可以知道

wait (),notify () 和 notifyAll () 方法需要在線程獲取到鎖的情況下才可以繼續(xù)執(zhí)行,所以這三個方法都需要放在同步代碼塊/方法中執(zhí)行,否則報異常:java.lang.IllegalMonitorStateException。

在同步代碼塊中,線程進入WAITING 狀態(tài)時,鎖會被釋放,不會導致該線程阻塞。反過來想下,如果鎖沒釋放,那其他線程就沒辦法獲取鎖,也就沒辦法喚醒它。

進入狀態(tài)

  • object.wait()
  • thread.join()
  • LockSupport.park()

退出狀態(tài)

  • object.notify()
  • object.notifyall()
  • LockSupport.unpark()

2.5.計時等待狀態(tài)(TIMED_WAITING)

一般是計時結束就會自動喚醒線程繼續(xù)執(zhí)行后面的程序,對于Object.wait(long) 方法還可以主動通知喚醒。

注意:Thread類下的sleep() 方法可以放在任意地方執(zhí)行;而wait(long) 方法和wait() 方法一樣,需要放在同步代碼塊/方法中執(zhí)行,否則報異常:java.lang.IllegalMonitorStateException。

進入狀態(tài)

  • Thread.sleep(long)
  • Object.wait(long)
  • Thread.join(long)
  • LockSupport.parkNanos(long)
  • LockSupport.parkNanos(Object blocker, long nanos)
  • LockSupport.parkUntil(long)
  • LockSupport.parkUntil(Object blocker, long deadline)

注:blocker 參數為負責此線程駐留的同步對象。

退出狀態(tài)

  • 計時結束
  • LockSupport.unpark(Thread)
  • object.notify()
  • object.notifyall()

2.6.終止(TERMINATED)

線程執(zhí)行結束

  • run()/call() 執(zhí)行完成
  • stop()線程
  • 錯誤或異常>>意外死亡

stop() 方法已棄用。

3.查看線程的6種狀態(tài)

通過一個簡單的例子來查看線程出現的6種狀態(tài)。

案例

public?class?Demo3?{
????private?static?Object?object?="obj";
????
????public?static?void?main(String[]?args)?throws?InterruptedException?{

????????Thread?thread0?=?new?Thread(()?->?{
????????????try?{
????????????????//?被阻塞狀態(tài)(BLOCKED)
????????????????synchronized?(object){
????????????????????System.out.println("thread0?進入:等待喚醒狀態(tài)(WAITING)");
????????????????????object.wait();
????????????????????System.out.println("thread0?被解除完成:等待喚醒狀態(tài)(WAITING)");
????????????????}
????????????????System.out.println("thread0?"+Thread.currentThread().getState());
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????});
????????//?新創(chuàng)建狀態(tài)(NEW)
????????System.out.println(thread0.getName()+":"+thread0.getState());

????????Thread?thread1?=?new?Thread(()?->?{
????????????try?{
????????????????System.out.println("thread1 進入:計時等待狀態(tài)(TIMED_WAITING)");
????????????????Thread.sleep(2);
????????????????System.out.println("thread1 出來:計時等待狀態(tài)(TIMED_WAITING)");
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????????//?被阻塞狀態(tài)(BLOCKED)
????????????synchronized?(object){
????????????????System.out.println("thread1 解除:等待喚醒狀態(tài)(WAITING)");
????????????????object.notify();
????????????????System.out.println("thread1 解除完成:等待喚醒狀態(tài)(WAITING)");
????????????}
????????????System.out.println("thread1?"+Thread.currentThread().getState());
????????});
????????//?新創(chuàng)建狀態(tài)(NEW)
????????System.out.println(thread1.getName()+":"+thread1.getState());

????????printState(thread0);
????????printState(thread1);

????????//?可運行狀態(tài)(RUNNABLE)
????????thread0.start();
????????//?可運行狀態(tài)(RUNNABLE)
????????thread1.start();

????}
????
????
????//?使用獨立線程來打印線程狀態(tài)
????private?static?void?printState(Thread?thread)?{
????????new?Thread(()->{
????????????while?(true){
????????????????System.out.println(thread.getName()+":"+thread.getState());
????????????????if?(thread.getState().equals(Thread.State.TERMINATED)){
????????????????????System.out.println(thread.getName()+":"+thread.getState());
????????????????????break;
????????????????}
????????????}
????????}).start();
????}
}

執(zhí)行結果:簡化后的輸出結果

Thread-0:NEW
Thread-1:NEW
Thread-0:RUNNABLE
Thread-1:RUNNABLE
thread0 進入:等待喚醒狀態(tài)(WAITING)
Thread-1:BLOCKED
thread1 進入:計時等待狀態(tài)(TIMED_WAITING)
Thread-0:BLOCKED
Thread-0:WAITING
……
Thread-0:WAITING
Thread-1:BLOCKED
Thread-1:TIMED_WAITING
……
Thread-1:TIMED_WAITING
Thread-1:BLOCKED
……
Thread-1:BLOCKED
Thread-0:WAITING
……
Thread-0:WAITING
thread1 出來:計時等待狀態(tài)(TIMED_WAITING)
Thread-0:WAITING
Thread-1:BLOCKED
thread1 解除:等待喚醒狀態(tài)(WAITING)
Thread-1:BLOCKED
Thread-0:WAITING
Thread-0:BLOCKED
thread1 解除完成:等待喚醒狀態(tài)(WAITING)
Thread-1:BLOCKED
thread1 RUNNABLE
Thread-0:BLOCKED
Thread-1:TERMINATED
thread0 被解除完成:等待喚醒狀態(tài)(WAITING)
Thread-0:BLOCKED
thread0 RUNNABLE
Thread-0:TERMINATED

圖片

最終的執(zhí)行結果如圖。

注意:因為案例中使用了獨立線程來打印不同線程的狀態(tài),會出現狀態(tài)打印稍微延遲的情況。

到此這篇關于一文詳解Java線程的6種狀態(tài)與生命周期的文章就介紹到這了,更多相關Java線程狀態(tài)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中stream處理中map與flatMap的比較和使用案例

    Java中stream處理中map與flatMap的比較和使用案例

    這篇文章主要介紹了Java中stream處理中map與flatMap的比較和使用案例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • java中把字符串轉成 double的方法

    java中把字符串轉成 double的方法

    Java 中可以使用 Double 類中的靜態(tài)方法 parseDouble() 將一個字符串轉換為 double 類型的數值,本文結合實例代碼對java字符串轉成 double詳細講解,需要的朋友參考下吧
    2023-08-08
  • 談談Spring AOP中@Aspect的高級用法示例

    談談Spring AOP中@Aspect的高級用法示例

    在Spring AOP中目前只有執(zhí)行方法這一個連接點,下面這篇文章主要給大家介紹了關于Spring AOP中@Aspect的高級用法的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-08-08
  • Go Java算法之從英文中重建數字示例詳解

    Go Java算法之從英文中重建數字示例詳解

    這篇文章主要為大家介紹了Go Java算法之從英文中重建數字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Zookeeper如何實現分布式服務配置中心詳解

    Zookeeper如何實現分布式服務配置中心詳解

    Zookeeper在實際使用場景很多,比如配置中心,分布式鎖,注冊中心等,下面這篇文章主要給大家介紹了關于Zookeeper如何實現分布式服務配置中心的相關資料,需要的朋友可以參考下
    2021-11-11
  • mybatis sum(參數) 列名作為參數的問題

    mybatis sum(參數) 列名作為參數的問題

    這篇文章主要介紹了mybatis sum(參數) 列名作為參數的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 深入探究Java中的類加載機制

    深入探究Java中的類加載機制

    這篇文章主要給大家介紹了關于Java中類加載機制的相關資料,JVM將類加載過程分為三個步驟:裝載(Load)、鏈接(Link)和初始化(Initialize),本文通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-09-09
  • WebUploader實現圖片上傳功能

    WebUploader實現圖片上傳功能

    這篇文章主要為大家詳細介紹了WebUploader實現圖片上傳功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Java實現學生管理系統(tǒng)詳解流程

    Java實現學生管理系統(tǒng)詳解流程

    這篇文章主要為大家詳細介紹了如何利用Java語言實現學生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java多種方法實現合并多個list對象列表

    Java多種方法實現合并多個list對象列表

    Java編程中,合并多個列表對象可以通過Stream?API或傳統(tǒng)循環(huán)方式實現,使用Stream?API合并時,利用flatMap方法將嵌套的List展平,再通過collect方法收集成一個新的列表,傳統(tǒng)循環(huán)則通過創(chuàng)建一個空的ArrayList,并通過遍歷每個列表將元素添加進去
    2024-09-09

最新評論

星座| 嘉义市| 嘉禾县| 池州市| 左云县| 乌拉特前旗| 云霄县| 淳安县| 长治市| 伊宁县| 晴隆县| 册亨县| 临海市| 盐山县| 辉南县| 博野县| 朝阳区| 张家界市| 保山市| 和静县| 阿勒泰市| 唐山市| 定结县| 永平县| 西林县| 莱阳市| 西安市| 襄城县| 正镶白旗| 三门峡市| 梁山县| 股票| 泰州市| 精河县| 襄汾县| 舒城县| 安岳县| 永安市| 湖南省| 凉城县| 漳州市|