偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

IO 阻塞期間,為什么線程狀態(tài)顯示 RUNNABLE?

開(kāi)發(fā) 前端
比較 Java 線程與操作系統(tǒng)線程,可以發(fā)現(xiàn) Java 線程狀態(tài)沒(méi)有可運(yùn)行狀態(tài)。也就是說(shuō) Java 線程 RUNNABLE 狀態(tài)包括了操作系統(tǒng)的可運(yùn)行狀態(tài)與運(yùn)行狀態(tài)。一個(gè)處于??RUNNABLE??狀態(tài) Java 線程,在操作系統(tǒng)層面狀態(tài)可能為可運(yùn)行狀態(tài),正在等待系統(tǒng)分配 CPU 使用權(quán)。

使用 Java 阻塞 I/O 模型讀取數(shù)據(jù),將會(huì)導(dǎo)致線程阻塞,線程將會(huì)進(jìn)入休眠,從而讓出 CPU 的執(zhí)行權(quán),直到數(shù)據(jù)讀取完成。這個(gè)期間如果使用 jstack 查看線程狀態(tài),卻可以發(fā)現(xiàn)Java 線程狀態(tài)是處于 RUNNABLE,這就和上面說(shuō)的存在矛盾,為什么會(huì)這樣?

上面的矛盾其實(shí)是混淆了操作系統(tǒng)線程狀態(tài)與 Java 線程狀態(tài)。這里說(shuō)的線程阻塞進(jìn)入休眠狀態(tài),其實(shí)是操作系統(tǒng)層面線程實(shí)際狀態(tài)。而我們使用 jstack 查看的線程狀態(tài)卻是 JVM 中的線程狀態(tài)。

線程是操作系統(tǒng)中一種概念,Java 對(duì)其進(jìn)行了封裝,Java 線程本質(zhì)上就是操作系統(tǒng)的中線程,其狀態(tài)與操作系統(tǒng)的狀態(tài)大致相同,但還是存在一些區(qū)別。

下面首先來(lái)看我們熟悉的 Java 線程狀態(tài)。

一、Java 線程狀態(tài)

Java 線程狀態(tài)定義在 Thread.State 枚舉中,使用  thread#getState 方法可以獲取當(dāng)前線程的狀態(tài)。

Thread.State 狀態(tài)如下圖:

圖片圖片

image

可以看到 Java 線程總共存在 6 中狀態(tài),分別為:

  • NEW(初始狀態(tài))
  • RUNNABLE(運(yùn)行狀態(tài))
  • BLOCKED(阻塞狀態(tài))
  • WATTING(等待狀態(tài))
  • TIMED_WAITING(限時(shí)等待狀態(tài))
  • TERMINATED(終止?fàn)顟B(tài))

每個(gè)使用new Thread()剛創(chuàng)建出線程實(shí)例狀態(tài)處于NEW狀態(tài),一旦調(diào)用thread.start(),線程狀態(tài)將會(huì)變成 RUNNABLE。

其中,RUNNABLE狀態(tài)的線程在進(jìn)入由synchronized修飾的方法或代碼塊前將會(huì)嘗試獲取一把隱式的排他鎖,一旦獲取不到,線程狀態(tài)將會(huì)變成BLOCKED,等待獲取鎖。一旦有其他線程釋放這把鎖,線程成功搶到該鎖,線程狀態(tài)就將會(huì)從BLOCKED轉(zhuǎn)變?yōu)?code style="background-color: rgb(231, 243, 237); padding: 1px 3px; border-radius: 4px; overflow-wrap: break-word; text-indent: 0px; display: inline-block;">RUNNABLE狀態(tài)。

而,處于WATTING狀態(tài)的線程將會(huì)一直處于無(wú)限期的等待狀態(tài),需要等待其他線程喚醒。總共存在三種方法將會(huì)使線程從 RUNNABLE變成WATTING。

  • Object#wait:線程在獲取到synchronized隱式鎖后,顯示的調(diào)用Object#wait()方法。這種情況下該線程將會(huì)讓出隱式鎖,一旦其他線程獲取到該鎖,且調(diào)用了Object.notify()object.notifyAll(),線程將會(huì)喚醒,然后變成RUNNABLE。
  • Thread#joinjoin方法是一種線程同步方法。假設(shè)我們?cè)?code style="background-color: rgb(231, 243, 237); padding: 1px 3px; border-radius: 4px; overflow-wrap: break-word; text-indent: 0px; display: inline-block;">main方法中執(zhí)行Thread A.join()方法,main線程狀態(tài)就會(huì)變成WATTING。直到A線程執(zhí)行完畢,main線程才會(huì)再變成RUNNABLE。
  • LockSupport#park()LockSupport是 JDK 并發(fā)包里重要對(duì)象,很多鎖的實(shí)現(xiàn)都依靠該對(duì)象。一旦調(diào)用 LockSupport#park(),線程就將會(huì)變?yōu)?WATTING 狀態(tài)。如果需要喚醒線程就需要調(diào)用 LockSupport#unpark,然后線程狀態(tài)重新變?yōu)?RUNNABLE。

TIMED_WAITINGWATTING 功能一樣,只不過(guò)前者增加限時(shí)等待的功能,一旦等待時(shí)間超時(shí),線程狀態(tài)自動(dòng)變?yōu)?RUNNABLE。以下幾種情況將會(huì)觸發(fā)這種狀態(tài):

  • 1.Thread#sleep(long millis)
  • 2.占有synchronized隱式鎖的線程調(diào)用Object.wait (long timeout)方法
  • 3.Thread#join (long millis)
  • 4.LockSupport#parkNanos (Object blocker, long deadline)
  • 5.LockSupport#parkUntil (long deadline)

線程一旦執(zhí)行結(jié)束或者線程執(zhí)行過(guò)程發(fā)生異常且未正常捕獲處理,狀態(tài)都將會(huì)自動(dòng)變成TERMINATED

Java 線程 6 種狀態(tài)看起來(lái)挺復(fù)雜的,但其實(shí)上面 BLOCKEDWATTING,TIMED_WAITING,都會(huì)使線程處于休眠狀態(tài),所以我們將這三類都?xì)w類為休眠狀態(tài)。這么分類的話,Java 線程生命周期就可以簡(jiǎn)化為下圖:

圖片

二、通用操作系統(tǒng)線程狀態(tài)

上面講完 Java 系統(tǒng)的線程狀態(tài),我們來(lái)看下通用操作系統(tǒng)的線程狀態(tài)。操作系統(tǒng)線程狀態(tài)可以分為初始狀態(tài),可運(yùn)行狀態(tài),運(yùn)行狀態(tài),休眠狀態(tài)以及終止?fàn)顟B(tài),如下圖:

圖片

這 5 中狀態(tài)詳細(xì)情況如下:

  • 1.初始狀態(tài),這時(shí)候線程剛被創(chuàng)建,還不能分配 CPU 。
  • 2.可運(yùn)行狀態(tài),線程等待系統(tǒng)分配 CPU ,從而執(zhí)行任務(wù)。
  • 3.運(yùn)行狀態(tài),操作系統(tǒng)將 CPU 分配給線程,線程執(zhí)行任務(wù)。
  • 4.休眠狀態(tài),運(yùn)行狀態(tài)下的線程如果調(diào)用阻塞 API,如阻塞方式讀取文件, 線程狀態(tài)就將變成休眠狀態(tài)。這種情況下,線程將會(huì)讓出 CPU 使用權(quán)。休眠結(jié)束,線程狀態(tài)將會(huì)先變成可運(yùn)行狀態(tài)。
  • 5.線程執(zhí)行結(jié)束或者執(zhí)行過(guò)程發(fā)生異常將會(huì)使線程進(jìn)入終止?fàn)顟B(tài),這個(gè)狀態(tài)下線程使命已經(jīng)結(jié)束。

三、對(duì)比兩者線程狀態(tài)

比較 Java 線程與操作系統(tǒng)線程,可以發(fā)現(xiàn) Java 線程狀態(tài)沒(méi)有可運(yùn)行狀態(tài)。也就是說(shuō) Java 線程 RUNNABLE 狀態(tài)包括了操作系統(tǒng)的可運(yùn)行狀態(tài)與運(yùn)行狀態(tài)。一個(gè)處于RUNNABLE狀態(tài) Java 線程,在操作系統(tǒng)層面狀態(tài)可能為可運(yùn)行狀態(tài),正在等待系統(tǒng)分配 CPU 使用權(quán)。

另外 Java 線程細(xì)分了操作系統(tǒng)休眠狀態(tài),分成了BLOCKED,WATTINGTIMED_WAITING三種。

當(dāng)線程調(diào)用阻塞式 API,線程進(jìn)入休眠狀態(tài),這里指的是操作系統(tǒng)層面的。從 JVM 層面,Java 線程狀態(tài)依然處于 RUNNABLE 狀態(tài)。JVM 并不關(guān)心操作系統(tǒng)線程實(shí)際狀態(tài)。從 JVM 看來(lái)等待 CPU 使用權(quán)(操作系統(tǒng)線程狀態(tài)為可運(yùn)行狀態(tài))與等待 I/O (操作系統(tǒng)線程狀態(tài)處于休眠狀態(tài))沒(méi)有區(qū)別,都是在等待某種資源,所以都?xì)w入 RUNNABLE 狀態(tài)。


責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2024-06-19 10:26:36

非阻塞IO客戶端

2023-12-06 07:28:47

阻塞IO異步IO

2021-10-13 06:49:15

網(wǎng)絡(luò) IO

2022-11-08 17:39:27

MySQLkilled

2024-01-09 18:09:43

模型方式DMA

2020-02-11 15:30:51

Redis快照數(shù)據(jù)庫(kù)

2009-06-29 18:00:05

Java多線程Runnable接口創(chuàng)建線程

2021-06-07 12:11:20

JavaRunning狀態(tài)

2010-03-16 18:59:15

Java Runnab

2025-01-14 08:42:34

IO流程序語(yǔ)句

2023-01-03 19:11:09

CPUI/O速度

2023-03-21 08:02:36

Redis6.0IO多線程

2023-12-20 14:35:37

Java虛擬線程

2024-11-28 11:07:50

線程JVM操作系統(tǒng)

2020-04-22 20:35:02

HashMap線程安全

2022-07-26 07:14:20

線程隔離Thread

2024-01-19 08:42:45

Java線程字符串

2023-12-13 09:45:49

模型程序

2017-04-20 13:33:12

代碼開(kāi)源PySonar

2020-04-29 14:10:44

Java線程池編程語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)