回顧前面部分的源碼分析,當(dāng)需要阻塞或喚醒一個線程的時候,都會使用LockSupport工具來完成相應(yīng)工作。LockSupport定義了一組公共靜態(tài)方法,這些方法提供了最基本的線程阻塞和喚醒公共,而LockSupport也成為構(gòu)建同步組件的基礎(chǔ)工具。
LockSupport定義了一組以park開頭的方法用來阻塞當(dāng)前線程,以及upark方法用來喚醒線程。這些方法如下所示:
| 方法名稱 | 描述 |
|---|---|
| void park() | 阻塞當(dāng)前線程,如果調(diào)用unpark(Thread)或者當(dāng)前線程被中斷,才能從park()方法返回 |
| void parkNanos(long nanos) | 阻塞當(dāng)前線程,最長不超過nanos納秒,返回條件在park()的基礎(chǔ)上增加了超時返回 |
| void parkUntil(long deadline) | 阻塞當(dāng)前線程,直到deadline |
| void unpark(Thread thread) | 喚醒處于阻塞的線程thread |
在Java 6新增了void park(Object blocker), void parkNanos(Object blocker, long nanos), void parkUntil(Object blocker, long deadline)三個方法,用以實現(xiàn)阻塞當(dāng)前線程的功能,其中參數(shù)blocker是用來標(biāo)識當(dāng)前線程在在等待的對象(以下稱阻塞對象),該對象主要用于問題排查和系統(tǒng)監(jiān)控。
下面的示例中,將對比parkNanos(long nanos)和parkNanos(Object blocker, long nanos)方法來展示阻塞對象blocker的用處,代碼片段和線程dump如下:
| 對比項\方法 | parkNanos(long nanos) | parkNanos(Object blocker, long nanos) |
|---|---|---|
| 代碼片段 | LockSupport.parkNanos(TimeUnit. SECONDS.toNanos(10)) |
LockSupport.parkNanos(test, TimeUnit.SECONDS.toNanos(10)); |
| 線程 dump 結(jié)果 |
"main" #1 prio=5 os_prio=0 tid= 0x0000025636fb9000 nid=0x1494 waiting on condition [0x000000bbe3fff000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park (java.base@10.0.2/Native Method) at java.util.concurrent.locks.LockSupport. parkNanos(java.base@10.0.2/ LockSupport.java:357) |
"main" #1 prio=5 os_prio=0 tid=0x000002b0ceda8800 nid=0x724 waiting on condition [0x000000c6acafe000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base @10.0.2/Native Method) - parking to wait for <0x00000006d119f9d8> (a p5.LockSupportTest) at java.util.concurrent.locks.LockSupport.parkNanos (java.base@10.0.2/LockSupport.java:234) |
從表中的線程dump結(jié)果可以看出,代碼片段的內(nèi)容是阻塞當(dāng)前線程10s,但從線程dump結(jié)果可以看出,有阻塞對象的parkNanos方法能夠傳遞給開發(fā)人員更多的線程信息。這是由于java 5之前,在線程阻塞(使用synchronized關(guān)鍵字)在一個對象上時,通過線程dump能夠查看到該線程的阻塞對象,方便問題定位,而在java 5推出的Lock等并發(fā)工具時卻遺漏了這一點,致使線程dump時無法提供阻塞對象的信息。因此,在java 6中,LockSupport新增了上述三個含有阻塞對象的park方法。
如果遺忘了如果進行線程dump操作,這里再溫習(xí)一下。
運行測試方法(不一定是"main")后,在終端輸入jps命令:
10964
2740 Launcher
9224 Program
12956 LockSupportTest
14300 KotlinCompileDaemon
7740 Jps
從中找到測試類對應(yīng)的線程id,此處是 12956,然后終端輸入jstack 12956,即可輸出線程dump信息,然后從中尋找到對應(yīng)測試方法的信息,此處為"main" #1 prio=5 os_prio=0 tid=0x0000025636fb9000 nid=0x1494 .....