Thread類的核心方法
JDK實現多線程編程的方式
-
繼承Thread類
-
實現Runnable接口
Thread的主要方法
currentThread()
返回代碼段正在被哪個線程調用的信息isAlive()
判斷當前的線程是否處於活動狀態sleep()
在指定的毫秒數內讓當前”正在執行的線程“休眠(暫停執行)getId()
取得線程的唯一標識
線程退出
線程退出的方法
- 線程正常退出
stop()
方法強行終止線程,但是會導致不可預料的結果(數據集修改一半等),與resume都是作廢過期的方法- 強制停止線程,立即停止;
- 該方法時不安全的(unsafe),會導致數據不一致的問題;
- 該方法可能拋出
java.lang.ThreadDeath
,因爲強制讓線程停止可能使得一些清理工作無法完成;
- 使用
interrupt()
方法中斷線程(該方法只是斷了一個退出的斷點,但線程不一定會及時的退出)- 假設當線程處理休眠狀態(調用了
sleep()
方法),調用該方法會拋出異常java.lang.InterruptedException
異常;
- 假設當線程處理休眠狀態(調用了
判斷線程是否是停止狀態
-
this.interrupted()
測試當前線程是否已經中斷- 靜態方法,測試當前線程是否已經打了中斷的標識
- 假設當前的線程是調用了
this.interrupt()
之後,調用一次之後,會將線程中的中斷標識移除,即第一次會得到true,第二次調用的時候獲得到false
-
this.isInterrupted()
測試線程是否已經中斷-
成員方法,可以測試某個具體線程是否被中斷
-
該方法不會移除中斷標識,所以只要某個線程被中斷過,那調用該接口則一直返回true
-
利用
this.isInterrupted()
和return
可以實現讓線程即時退出,當調用了this.interrupt()
則通過邏輯保證讓線程能夠及時的退出,範例:for (條件) { if (this.isInterrupted()) { return; } }
-
線程暫停
線程暫停的方法
suspend()
可以暫停線程執行resume()
可以恢復線程執行
suspend()和resume()的缺點
獨佔
suspend()
和resume()
需要搭配使用,如果沒有配套使用,當使用了suspend()
在暫停了線程的執行,那沒有調用resume()
線程會一直休眠下去;
如果這個時候剛好在某個同步代碼塊中使用了suspend()
,那麼這個同步代碼塊的資源會被永久佔用
不同步
使用suspend()
和resume()
方法容易出現因爲線程暫停而導致的髒數據問題(即無法保證suspend()
之前的業務操作回滾或者原子)
讓出CPU資源
yield()
的作用是讓出當前的CPU資源,將CPU資源讓給其他的線程;一次只讓一個時鐘週期,可能在當前時鐘週期的前中後
線程的優先級
線程的優先級
- 優先級越高,則獲取的CPU資源相對越多
- Java中劃分1-10這10個線程優先級
優先級的繼承性
當設置了A線程的優先級,然後由A線程啓動了B線程,那麼B線程會繼承A線程的優先級;
優先級的規則性
不關代碼的順序,設置了較高的優先級的線程理論上獲取CPU時間的概率會比其他線程高;
優先級具有隨機性
設置了優先級,只是保證在理論情況下優先級高的會獲得比較多的CPU時間,儘量安排多的CPU時間給高優先級線程,但是不能保證一定每次都分配足夠多的CPU時間給到對應線程;即不一定每次高優先級的線程都比低優先級的線程先執行完;
守護線程
Java中有兩種線程
- 守護線程(通過
setDaemon(true)
的方式設置) - 非守護線程
守護線程的生命週期
只要有一個非守護線程的存在,守護線程會生存(最著名的就是GC線程),當所有的非守護線程都退出了,那麼守護線程也就退出了