Java并发编程的基础-线程的终止原理
我們來看一下?thread.interrupt()方法做了什么事情
這個方法里面,調用了interrupt0(),這個方法在前面分析start方法的時候見過,是一個native方法,這里就不再重復貼代碼了,同樣,我們找到jvm.cpp文件,找到JVM_Interrupt的定義?
這個方法比較簡單,直接調用了?Thread::interrupt(thr)這個方法,這個方法的定義在Thread.cpp文件中,代碼如下
Thread::interrupt方法調用了os::interrupt方法,這個是調用平臺的interrupt方法,這個方法的實現是在?os_*.cpp文件中,其中星號代表的是不同平臺,因為jvm是跨平臺的,所以對于不同的操作平臺,線程的調度方式都是不一樣的。我們以os_linux.cpp文件為例?
set_interrupted(true)實際上就是調用osThread.hpp中的set_interrupted()方法,在osThread中定義了一個成員屬性volatile jint _interrupted;?
通過上面的代碼分析可以知道,thread.interrupt()方法實際就是設置一個interrupted狀態標識為true、并且通過ParkEvent的unpark方法來喚醒線程。
1. 對于synchronized阻塞的線程,被喚醒以后會繼續嘗試獲取鎖,如果失敗仍然可能被park?
2. 在調用ParkEvent的park方法之前,會先判斷線程的中斷狀態,如果為true,會清除當前線程的中斷標識?
3. Object.wait、Thread.sleep、Thread.join會拋出InterruptedException?
這里給大家普及一個知識點,為什么Object.wait、Thread.sleep和Thread.join都會拋出InterruptedException??你會發現這幾個方法有一個共同點,都是屬于阻塞的方法?
而阻塞方法的釋放會取決于一些外部的事件,但是阻塞方法可能因為等不到外部的觸發事件而導致無法終止,所以它允許一個線程請求自己來停止它正在做的事情。當一個方法拋出InterruptedException時,它是在告訴調用者如果執行該方法的線程被中斷,它會嘗試停止正在做的事情并且通過拋出InterruptedException表示提前返回。
所以,這個異常的意思是表示一個阻塞被其他線程中斷了。然后,由于線程調用了interrupt()中斷方法,那么Object.wait、Thread.sleep等被阻塞的線程被喚醒以后會通過is_interrupted方法判斷中斷標識的狀態變化,如果發現中斷標識為true,則先清除中斷標識,然后拋出
InterruptedException?
需要注意的是,InterruptedException異常的拋出并不意味著線程必須終止,而是提醒當前線程有中斷的操作發生,至于接下來怎么處理取決于線程本身,比如
1. 直接捕獲異常不做任何處理
2. 將異常往外拋出?
3. 停止當前線程,并打印異常信息?
為了讓大家能夠更好的理解上面這段話,我們以Thread.sleep為例直接從jdk的源碼中找到中斷標識的清除以及異常拋出的方法代碼?
找到?is_interrupted()方法,linux平臺中的實現在os_linux.cpp文件中,代碼如下?
找到Thread.sleep這個操作在jdk中的源碼體現,怎么找?
相信如果前面大家有認真看的話,應該能很快找到,代碼在jvm.cpp文件中?
注意上面加了中文注釋的地方的代碼,先判斷is_interrupted的狀態,然后拋出一個InterruptedException異常。到此為止,我們就已經分析清楚了中斷的整個流程。
?
總結
以上是生活随笔為你收集整理的Java并发编程的基础-线程的终止原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java并发编程的基础-为什么要复位
- 下一篇: Synchronized结合Java O