線程的禁忌你踩坑了嗎

程序員小迷 2024-04-28 14:13:09

一、暫停、恢複和停止操作對應在線程Thread的API是suspend()、resume()和stop()。

但是這些API不建議使用,因爲這些方法會帶來副作用。比如:suspend()方法在調用後,線程不會釋放已經占有的資源(比如鎖),而是占有著資源進入挂起狀態,這樣容易引發死鎖。同樣,stop()方法在終結一個線程時不會保證線程的資源正常釋放,通常是沒有給予線程完成資源釋放工作的機會,因此會導致程序可能工作在不確定狀態。

推薦配合使用Object的wait()、notify()、notifyAll()來控制線程的執行。

二、終止一個線程

1.安全的中止一個線程是其他線程通過調用某個線程A的interrupt()方法對其進行中斷操作。

中斷好比其他線程對該線程打了個招呼,"線程A,你要中斷了",不代表線程A會立即停止自己的工作,同樣的線程A完全可以不理會這種中斷請求。Java裏的線程默認是搶占式的,可以調用yield或join等方法變成協作式的調度。

2.線程通過檢查自身的中斷標志位是否被置爲true來進行響應,線程通過方法isInterrupted()來進行判斷是否被中斷,也可以調用靜態方法Thread.interrupted()來進行判斷當前線程是否被中斷,不過靜態方法Thread.interrupted()會同時將中斷標識位改寫爲false。

3.如果一個線程處于了阻塞狀態(如線程調用了Thread.sleep、Thread.join),則線程在檢查中斷標示時如果發現中斷標示爲true,則會在這些阻塞方法調用處抛出InterruptedException異常,並且在抛出異常後會立即將線程的中斷標示位清除,即重新設置爲false。

4.不建議自定義一個取消標志位來中止線程的運行。因爲run方法裏有阻塞調用時會無法很快檢測到取消標志,線程必須從阻塞調用返回後,才會檢查這個取消標志。這種情況下,使用中斷會更好,因爲:

1)一般的阻塞方法,如sleep等本身就支持中斷的檢查。

2)檢查中斷位的狀態和檢查取消標志位沒什麽區別,用中斷位的狀態還可以避免聲明取消標志位,減少資源的消耗。

5.處于死鎖狀態的線程無法被中斷。

三、start()方法讓一個線程進入就緒隊列等待分配CPU,分到CPU後才調用實現的run()方法,而且start()方法不能重複調用。

四、yield()方法:使當前線程讓出CPU占有權,但讓出的時間是不可設定的。也不會釋放鎖資源,所有執行yield()的線程有可能在進入到可執行狀態後馬上又被執行。

五、join方法:將兩個交替執行的線程合並爲順序執行的線程。比如在線程B中調用了線程A的join()方法,則直到線程A執行完畢後,才會繼續執行線程B。

六、其他

1.不要依賴線程優先級,因爲操作系統可能會忽略它。

2.避免在構造函數或finalize()方法中啓動線程。構造函數中對象可能還未完全構造好。finalize()的調用時機不確定。

3.頻繁創建銷毀線程開銷大,應該使用線程池,例如:ExecutorService。

4.不應在多個線程共享一個SimpleDateFormat實例,因爲它不是線程安全的。

5.守護線程在JVM退出時不會阻止JVM的關閉,故不能在守護線程運行長時間執行的任務。

微風不燥,陽光正好,你就像風一樣經過這裏,願你停留的片刻溫暖舒心。

我是程序員小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等編程技術的技巧經驗分享),若作品對您有幫助,請關注、分享、點贊、收藏、在看、喜歡,您的支持是我們爲您提供幫助的最大動力。

歡迎關注。助您在編程路上越走越好!

1 阅读:19

程序員小迷

簡介:致力于Android、C等編程技術的技巧經驗分享