Java終止線程的幾種方式實例總結(jié)
一、正常運行結(jié)束
所謂正常運行結(jié)束,就是程序正常運行結(jié)束,線程自動結(jié)束。
public class ThreadTest extends Thread { public void run() { //do something } }
二、使用退出標志退出線程
一般run()方法執(zhí)行完,線程就會正常結(jié)束,然而,常常有些線程是伺服線程。他們需要長時間的運行,只有在外部某些條件滿足的情況下,才能關(guān)閉這些線程。使用一個變量來控制循環(huán),例如:最直接的方法就是設(shè)一個boolean類型的標志,并通過設(shè)置這個標志位true或false來控制while循環(huán)是否退出,下面放代碼:
public class ThreadTest extends Thread { public volatile boolean exit = false; public void run() { while (!exit){ //do something } } }
三、interrupt方法結(jié)束線程
使用interrupt()方法來中斷線程是分兩種情況的:
- 線程處于阻塞狀態(tài):如使用了sleep(),同步鎖的wait(),socket中的receiver(),accept()等方法時,會使線程處于阻塞狀態(tài)。當調(diào)用線程interrupt()方法時,會拋出InterruptException異常。阻塞中的那個方法拋出此異常,通過代碼可以捕獲此異常,然后跳出循環(huán)狀態(tài),從而讓我們有機會結(jié)束這個線程的執(zhí)行。并不是只要調(diào)用interrupt()方法,線程就會結(jié)束,實際上是不正確的,一定要先捕獲InterruptException異常之后通過break來跳出循環(huán),才能正常結(jié)束run()方法。
- 線程未處于阻塞狀態(tài):使用isInterrupted()判斷線程的中斷標志來退出循環(huán)。當使用interrupt()方法時,中斷標志就會為true,和使用自定義的標志來控制循環(huán)是一樣的道理。
public class ThreadTest extends Thread { public void run() { while(!isInterrupted()) { try { Thread.sleep(5*1000); } catch(InterruptedException e) { e.printStackTrace(); break;//捕獲到異常之后,執(zhí)行break跳出循環(huán) } } } }
四、stop()方法終止線程(不安全)
我們可以直接使用thread.stop()來強行終止線程,但是stop()方法是很危險的,就想突然關(guān)閉電源一樣。這樣子可能機會產(chǎn)生不可預(yù)料的結(jié)果,不安全主要是:
- thread.stop()調(diào)用之后,創(chuàng)建子線程的線程就會拋出ThreadDeatherror的錯誤,并且會釋放子線程所持有的所有鎖。一般任何進行加鎖的代碼塊,都是為了保護數(shù)據(jù)的一致性,如果在調(diào)用thread.stop()后導(dǎo)致了該線程所持有的所有的鎖突然釋放,那么被保護的數(shù)據(jù)就可能呈現(xiàn)不一致性,其他線程在使用這些被破壞的數(shù)據(jù)時,有可能導(dǎo)致一些很奇怪的應(yīng)用程序錯誤。因此,并不推薦使用stop()方法來終止線程。
五、線程相關(guān)
5.1 sleep()和wait()區(qū)別
- 對于sleep()方法,我們首先要知道該方法是屬于Thread類中的,而wait()方法,則是屬于Object類中的。
- sleep()方法導(dǎo)致了程序暫停執(zhí)行指定的時間,讓出CPU給其他線程,但是它依然處于監(jiān)控狀態(tài),當指定時間到了又會自動恢復(fù)運行狀態(tài)。
- 調(diào)用sleep()方法的過程中,線程不會釋放對象鎖。
- 調(diào)用wait()方法的時候,線程會釋放對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調(diào)用notify()方法后本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態(tài)。
5.2 start()和run()的區(qū)別
- start()方法來啟動線程,真正實現(xiàn)了多線程運行。這時無需等待run()方法體代碼執(zhí)行完畢,可以繼續(xù)執(zhí)行下面的代碼。
- 通過調(diào)用Thread類的start()方法來啟動一個線程,此時線程是處于就緒狀態(tài),并沒有運行。
- 方法run()稱為線程體,它包含了要執(zhí)行的這個線程的內(nèi)容,次線程終止。然后CPU在調(diào)度其他線程。
5.3 Java后臺線程(守護線程)
- 定義:守護線程–也稱“服務(wù)線程”,他是后臺線程,它有一個特性,即為用戶線程 提供 公共服務(wù),在沒有用戶線程可服務(wù)時會自動離開。
- 優(yōu)先級:守護線程的優(yōu)先級比較低,用于為系統(tǒng)中的其它對象和線程提供服務(wù)。
設(shè)置:通過setDaemon(true)來設(shè)置線程為“守護線程”;將一個用戶線程設(shè)置為守護線程的方式是在 線程對象創(chuàng)建 之前 用線程對象的setDaemon方法。 - 在Daemon線程中產(chǎn)生的新線程也是Daemon的。
- 守護線程則是JVM級別的,以Tomcat 為例,如果你在Web 應(yīng)用中啟動一個線程,這個線程的生命周期并不會和Web應(yīng)用程序保持同步。也就是說,即使你停止了Web應(yīng)用,這個線程依舊是活躍的。
- example: 垃圾回收線程就是一個經(jīng)典的守護線程,當我們的程序中不再有任何運行的Thread,程序就不會再產(chǎn)生垃圾,垃圾回收器也就無事可做,所以當垃圾回收線程是JVM上僅剩的線程時,垃圾回收線程會自動離開。它始終在低級別的狀態(tài)中運行,用于實時監(jiān)控和管理系統(tǒng)中的可回收資源。
- 生命周期:守護進程(Daemon)是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。也就是說守護線程不依賴于終端,但是依賴于系統(tǒng),與系統(tǒng)“同生共死”。當JVM中所有的線程都是守護線程的時候,JVM就可以退出了;如果還有一個或以上的非守護線程則JVM不會退出。
總結(jié)
到此這篇關(guān)于Java終止線程的幾種方式的文章就介紹到這了,更多相關(guān)Java終止線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis.type-aliases-package之巨坑的解決
這篇文章主要介紹了mybatis.type-aliases-package之巨坑的解決,具有很好的參考價值,希望對大家有所幫助。2021-09-09

詳解SpringBoot中異步請求和異步調(diào)用(看完這一篇就夠了)

WebSocket獲取httpSession空指針異常的解決辦法

解決SpringBoot加載application.properties配置文件的坑

SpringCloud實現(xiàn)文件上傳功能的方法詳解