鍍金池/ 教程/ Java/ 守護(hù)線程與線程阻塞
并發(fā)新特性—信號(hào)量 Semaphore
線程間協(xié)作:wait、notify、notifyAll
notify 通知的遺漏
notifyAll 造成的早期通知問題
多線程的實(shí)現(xiàn)方法
深入 Java 內(nèi)存模型(1)
多線程環(huán)境下安全使用集合 API
并發(fā)新特性—Lock 鎖與條件變量
生產(chǎn)者—消費(fèi)者模型
深入 Java 內(nèi)存模型(2)
線程中斷
Volatile 關(guān)鍵字(上)
并發(fā)新特性—阻塞隊(duì)列與阻塞棧
可重入內(nèi)置鎖
守護(hù)線程與線程阻塞
并發(fā)新特性—障礙器 CyclicBarrier
Volatile 關(guān)鍵字(下)
synchronized 關(guān)鍵字
synchronized 的另個(gè)一重要作用:內(nèi)存可見性
并發(fā)新特性—Executor 框架與線程池
并發(fā)性與多線程介紹
死鎖
實(shí)現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile
線程掛起、恢復(fù)與終止

守護(hù)線程與線程阻塞

守護(hù)線程

Java 中有兩類線程:User Thread(用戶線程)、Daemon Thread(守護(hù)線程)

用戶線程即運(yùn)行在前臺(tái)的線程,而守護(hù)線程是運(yùn)行在后臺(tái)的線程。 守護(hù)線程作用是為其他前臺(tái)線程的運(yùn)行提供便利服務(wù),而且僅在普通、非守護(hù)線程仍然運(yùn)行時(shí)才需要,比如垃圾回收線程就是一個(gè)守護(hù)線程。當(dāng) VM 檢測(cè)僅剩一個(gè)守護(hù)線程,而用戶線程都已經(jīng)退出運(yùn)行時(shí),VM就會(huì)退出,因?yàn)闆]有如果沒有了被守護(hù)這,也就沒有繼續(xù)運(yùn)行程序的必要了。如果有非守護(hù)線程仍然存活,VM 就不會(huì)退出。

守護(hù)線程并非只有虛擬機(jī)內(nèi)部提供,用戶在編寫程序時(shí)也可以自己設(shè)置守護(hù)線程。用戶可以用 Thread 的 setDaemon(true)方法設(shè)置當(dāng)前線程為守護(hù)線程。

雖然守護(hù)線程可能非常有用,但必須小心確保其他所有非守護(hù)線程消亡時(shí),不會(huì)由于它的終止而產(chǎn)生任何危害。因?yàn)槟悴豢赡苤涝谒械挠脩艟€程退出運(yùn)行前,守護(hù)線程是否已經(jīng)完成了預(yù)期的服務(wù)任務(wù)。一旦所有的用戶線程退出了,虛擬機(jī)也就退出運(yùn)行了。 因此,不要在守護(hù)線程中執(zhí)行業(yè)務(wù)邏輯操作(比如對(duì)數(shù)據(jù)的讀寫等)。

另外有幾點(diǎn)需要注意:

  • setDaemon(true)必須在調(diào)用線程的 start()方法之前設(shè)置,否則會(huì)跑出 IllegalThreadStateException 異常。
  • 在守護(hù)線程中產(chǎn)生的新線程也是守護(hù)線程。
  • 不要認(rèn)為所有的應(yīng)用都可以分配給守護(hù)線程來進(jìn)行服務(wù),比如讀寫操作或者計(jì)算邏輯。

線程阻塞

線程可以阻塞于四種狀態(tài):

  • 當(dāng)線程執(zhí)行 Thread.sleep()時(shí),它一直阻塞到指定的毫秒時(shí)間之后,或者阻塞被另一個(gè)線程打斷;
  • 當(dāng)線程碰到一條 wait()語(yǔ)句時(shí),它會(huì)一直阻塞到接到通知(notify())、被中斷或經(jīng)過了指定毫秒時(shí)間為止(若制定了超時(shí)值的話)
  • 線程阻塞與不同 I/O 的方式有多種。常見的一種方式是 InputStream的read()方法,該方法一直阻塞到從流中讀取一個(gè)字節(jié)的數(shù)據(jù)為止,它可以無限阻塞,因此不能指定超時(shí)時(shí)間;
  • 線程也可以阻塞等待獲取某個(gè)對(duì)象鎖的排他性訪問權(quán)限(即等待獲得 synchronized 語(yǔ)句必須的鎖時(shí)阻塞)。

注意,并非所有的阻塞狀態(tài)都是可中斷的,以上阻塞狀態(tài)的前兩種可以被中斷,后兩種不會(huì)對(duì)中斷做出反應(yīng)