在Java中有以下三種方法可以終止正在啟動並執行線程: 使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止 使用stop方法強行終止線程,但不推薦使用這種方法,因為stop和suspend及resume一樣,都是作廢到期的方法,使用它們可能產生不可預料的結果 使用interrupt方法中斷線程,不過interrupt方法不會終止一個正常啟動並執行線程,只會給它設定一個中斷標記,需要對其進行判斷來停止線程運行
判斷線程是否是停止狀態有兩個方法: this.interrupted():測試當前線程是否已經中斷,是一個靜態方法,執行後會將中斷標誌為false this.isInterrupted():測試線程是否已經中斷,非靜態方法,不會清除中斷標誌
stop()方法已經被作廢,因為如果強制讓線程停止則有可能使一些清理性的工作得不到完成。另外一個情況就是對鎖定的對象進行了“解鎖”,導致資料得不到同步的處理,出現資料不一致的問題。
suspend和resume方法會造成公用的同步對象的獨佔,如PrintlnStream的println方法的獨佔,使得其他線程無法訪問公用同步對象。另外使用這兩個方法時也容易造成因為線程的暫停而導致資料不同步的情況。
關鍵字synchronized的鎖是對象鎖,而不是把一段代碼或者函數當做鎖。所以,假如A線程先持有object對象的Lock鎖,B線程可以以非同步方式調用object對象中的非synchronized類型的方法,但是如果B線程想要調用object對象中的任何synchronized類型的方法,就需要等待,也就是同步。
synchronized擁有鎖重入的功能,也就是說在使用synchronized時,當一個線程得到一個對象鎖後,再次請求此對象鎖時是可以再次得到該對象鎖的。也就是說,在一個synchronized方法的內部調用本類其它synchronized方法時是可以得到鎖的。當兩個類之間存在繼承關係時,子類是可以通過“可重新進入鎖”來調用父類的同步方法的。當一個線程執行的代碼出現異常時,其所持有的鎖會自動釋放。
synchronized(x)格式的寫法是將x對象本身作為對象監視器,這樣就可以得到以下三個結論: 當多個線程同時執行synchronized(x) {}同步代碼塊時呈同步效果 當其他線程執行x對象中的同步方法時呈同步效果 當其他線程執行x對象方法裡面的synchronized(this)代碼塊時也呈同步效果
synchronized用在static方法上可以對整個類加鎖,就是應用到所有類的對象上面,和synchronized(x.class)的作用一樣。子類如果重寫了父類的synchronized方法,子類的方法並不繼承其synchronized特性,仍需顯式地添加synchronized標誌。
關鍵字volatile主要的使用場合是在多個線程中可以感知執行個體變數被更改了,並且可以獲得最新的值使用,也就是用多線程讀取執行個體變數時可以獲得最新的值引使用。volatile本身並不處理資料的原子性,而是強制對資料的讀寫及時影響到主記憶體。關鍵字synchronized也具有將工作中的私人變數與公用記憶體中的變數同步的功能。
線上程調用wait()/notify()方法之前必須要獲得該對象的對象層級鎖,否則會拋出IllegalMonitorStateException運行時異常。在執行notify()方法之後,當前線程並不馬上釋放該對象鎖,要等到調用notify()方法的線程將程式執行完,也就是退出synchronized代碼塊之後,當前線程才會釋放鎖。
join()在內部使用wait()方法進行等待,而synchronized關鍵字使用的是對象監視器原理作為同步。在某個線程join另一個線程(即等待另一個線程時),如果當前線程(等待別的線程的線程)被中斷,則當前線程會拋出異常。
join(long)中的是設定等待的時間,join(long)的功能在是用wait(long)來實現的,所以join(long)方法具有釋放鎖的特點。而sleep(long)是不會釋放鎖的。