1. 程式人生 > >多執行緒和併發。

多執行緒和併發。

  • 不推薦覆寫start方法
  • 啟動執行緒前stop方法是不可靠的
  • 不使用stop方法停止執行緒

        有以下三個問題:

        1、stop方法是過時的

        2、stop方法會導致程式碼邏輯不完整

        3、stop方法會破壞原子邏輯

        如果期望終止一個正在執行的執行緒,則不能使用已經過時的stop方法,需要自行編碼實現,如此即可保證原子邏輯不被破壞,程式碼邏輯不會出現異常。當然,如果我們使用的是執行緒池(比如ThreadPoolExecutor類),那麼可以通過shutdown方法逐步關閉池中的執行緒,他採用的是比較溫和、安全的關閉執行緒方法,完全不會產生類似stop方法的弊端。

  • 執行緒優先順序只使用三個等級
        執行緒優先順序推薦使用MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY三個級別,不建議使用其他7個數字。
  • 使用執行緒異常處理器提升系統可靠性

        Java 1.5版本以後在Thread類中增加了setUncaughtExceptionHandler方法,實現了執行緒異常的捕捉和處理。

        實際環境中應用,需要注意以下三個方面:

        1、共享資源鎖定

        2、髒資料引起系統邏輯混亂

        3、記憶體溢位

  • volatile不能保證資料同步
        注意:volatile不能寶恆資料是同步的,只能保證執行緒能夠獲得最新值。

  • 非同步運算考慮使用Callable介面

        從Java 1.5開始引入了一個新的介面Callable,他類似於Runable介面,實現他就可以實現多執行緒任務。

        此類非同步計算的好處是:

        1、儘可能多地佔用系統資源,提供快速運算。

        2、可以監控執行緒執行的情況,比如是否執行完畢、是否有返回值、是否有異常等。

        3、可以為使用者提供更好的支援,比如例子中的運算進度等。

  • 優先選擇執行緒池

        一個執行緒的執行時間分為三部分:T1為執行緒啟動時間,T2為執行緒體的執行時間,T3為執行緒銷燬時間,如果一個執行緒不能被重複使用,每次建立一個執行緒都需要經過啟動、執行、銷燬這三個過程,那麼這勢必會增大系統的響應時間,有沒有更好的辦法降低執行緒的執行時間呢?

        T2是無法避免的,只有通過優化程式碼來實現降低執行時間。T1和T2都可以通過執行緒池(Thread Pool)來縮減時間,比如在容器(或系統)啟動時,建立足夠多的執行緒,當容器(或系統)需要時直接從執行緒池中獲得執行緒,運算出結果,再把執行緒返回到執行緒池中。

        執行緒池的建立過程:建立一個阻塞佇列以容納任務,在第一次執行任務時建立足夠多的執行緒(不超過許可執行緒數),並處理任務,之後每個工作執行緒自行從任務佇列中獲得任務,直到任務佇列中的任務數量為0為止,此時執行緒將處於等待狀態,一旦有任務再加入到佇列中,即喚醒工作執行緒進行處理,實現執行緒的可複用性。

        使用執行緒減少的是執行緒的建立和銷燬時間。

  • 適時選擇不同的執行緒池來實現、

        Java的執行緒池實現從最根本上來說只有兩個:ThreadPoolExecutor類和ScheduledThreadPoolExecutor類,這兩個類還是父子關係,但是Java為了簡化平行計算,還提供了一個Executors的靜態類,他可以直接生成多種不同的執行緒池執行器,比如單執行緒執行器、帶緩衝功能的執行器等,但歸根結底還是使ThreadPoolExecutor類或ScheduledThreadPoolExecutor類的封裝性。

        newSingleThreadExecutor、newCachedThreadPool、newFixedThreadPool是執行緒的簡化版,而ThreadPoolExecutor則是旗艦版——簡化版更容易操作,需要了解的知識相對少些,方便實用,而且旗艦版功能齊全,適用面廣,但難於駕馭。

  • Lock與synchronized是不一樣的

        顯示鎖和內部鎖的不同之處:

        1、Lock支援更細粒度的鎖控制

        2、Lock是無阻塞鎖,synchronized是阻塞鎖

        3、Lock可實現公平鎖,synchronized只能是非公平鎖

        4、Lock是程式碼級的,synchronized是JVM級的

        根據實際情況考慮:靈活、強大則選擇Lock,快捷、安全則選擇synchronized。

  • 預防執行緒死鎖

        在我們Java多執行緒併發程式設計中,死鎖很難避免,也不容易預防,對付他的最好辦法是測試:提高測試覆蓋率,建立有效地邊界測試,加強資源監控,這些方法能使死鎖無處遁形,即使發生了死鎖現象也能迅速查詢到原因,提高系統的可靠性。

  • 適當設定阻塞佇列長度
  • 使用CountDownLatch協調子執行緒
  • CyclicBarrier讓多執行緒齊步走
        在多執行緒程式設計中,兩個執行緒獨立執行,在沒有執行緒間通訊的情況下,如何解決兩個執行緒彙集在同一遠點的問題。Java提供了CyclicBarrier(關卡,也有翻譯為柵欄)工具類來實現。