java併發程式設計實戰學習(3)–基礎構建模組

文藝小青年發表於2017-11-16

5.3阻塞佇列和生產者-消費者模式

BlockingQueue阻塞佇列提供可阻塞的put和take方法,以及支援定時的offer和poll方法。如果佇列已經滿了,那麼put方法將阻塞直到空間可用;如果佇列為空,那麼take方法將阻塞直到有元素可用。佇列可以是有界的也可以是無界的。

如果生產者生成工作的速率比消費者處理工作的速率款,那麼工作項會在佇列中累計起來,最終好緊記憶體。同樣,put方法的阻塞特性也極大地簡化了生產者的編碼。如果使用有界佇列,當佇列充滿時,生產者將阻塞並不能繼續生產工作,而消費者就有時間來趕上工作的進度。阻塞佇列同樣提供了一個offer方法,如果資料項不能被新增到佇列中,那麼將返回一個失敗的狀態。這樣你就能建立更多靈活的策略來處理負荷過載的情況。

在構建高可靠的應用程式時,有界佇列是一種強大的資源管理工具:他們能一直並防止產生過多的工作項,使應用程式在負荷過載的情況下邊的更加健壯。

  5.5訊號量

Semaphore中管理著一組虛擬的許可(permit)。許可的初始數量可通過建構函式來指定。在執行操作時可以首先獲得許可(只要還有剩餘的許可),並在使用以後釋放許可。如果沒有許可,那麼acquire將阻塞直到有許可(或者被中斷或者操作超時)。release方法將返回一個許可給訊號量。計算訊號量的一種簡化形式是二值訊號量,即初始值為1的Semaphore。二值訊號量可以用作互斥體(mutex),並具備不可重入的加鎖語義:誰擁有這個唯一的許可,誰就擁有了互斥鎖。

  5.6構建高效且可伸縮的結果快取

  小結:

  • 可變狀態是直觀重要的(It`s the mutable state,stupid)。所有的併發問題都可以歸結為如何協調對併發狀態的訪問。可變狀態越少,就越容易確保執行緒的安全性。
  • 儘量將域宣告為final型別,除非需要他們是可變的。
  • 不可變物件一定是執行緒安全的。不可變物件能極大地降低併發程式設計的複雜性。他們更為簡單而且可以任意共享而無須使用加鎖或保護性複製等機制。
  • 封裝有助於管理複雜性。在編寫執行緒安全的程式時,雖然可以將所有資料都儲存在全域性變數中,但為什麼要這樣做?將資料封裝在物件中,更易於維持不變性條件:將同步機制封裝在物件中,更易於遵循同步策略。
  • 用鎖來保護每個可變變數。
  • 當保護同一個不變性條件中的所有變數時,要使用同一個鎖。
  • 在執行復合操作期間,要持有鎖。
  • 如果從多個執行緒中訪問同一個可變變數時沒有同步機制,那麼程式會出現問題。
  • 不要故作聰明地腿短出不需要使用同步。
  • 在設計過程中考慮執行緒安全,或者在文件中明確地指出他不是執行緒安全的。
  • 將同步策略文件化。

  

本文轉自Ryan.Miao部落格園部落格,原文連結:http://www.cnblogs.com/woshimrf/p/5251959.html,如需轉載請自行聯絡原作者


相關文章