介面 Condition

来源:http://www.cnblogs.com/Yalena/archive/2017/06/15/7020534.html
-Advertisement-
Play Games

java.util.concurrent.locks 介面 Condition Condition 將 Object 監視器方法(wait、notify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現組合使用,為每個對象提供多個等待 set(wait-set) ...


java.util.concurrent.locks 介面 Condition

所有已知實現類:
AbstractQueuedLongSynchronizer.ConditionObject, AbstractQueuedSynchronizer.ConditionObject

public interface Condition

ConditionObject 監視器方法(waitnotifynotifyAll分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用

條件(也稱為條件隊列條件變數)為線程提供了一個含義,以便在某個狀態條件現在可能為 true 的另一個線程通知它之前,一直掛起該線程(即讓其“等待”)。因為訪問此共用狀態信息發生在不同的線程中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,並掛起當前線程,就像 Object.wait 做的那樣。

Condition 實例實質上被綁定到一個鎖上。要為特定 Lock 實例獲得 Condition 實例,請使用其 newCondition() 方法。

作為一個示例,假定有一個綁定的緩衝區,它支持 puttake 方法。如果試圖在空的緩衝區上執行 take 操作,則在某一個項變得可用之前,線程將一直阻塞;如果試圖在滿的緩衝區上執行 put 操作,則在有空間變得可用之前,線程將一直阻塞。我們喜歡在單獨的等待 set 中保存 put 線程和 take 線程,這樣就可以在緩衝區中的項或空間變得可用時利用最佳規劃,一次只通知一個線程。可以使用兩個 Condition 實例來做到這一點。

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }
 

ArrayBlockingQueue 類提供了這項功能,因此沒有理由去實現這個示例類。)

Condition 實現可以提供不同於 Object 監視器方法的行為和語義,比如受保證的通知排序,或者在執行通知時不需要保持一個鎖。如果某個實現提供了這樣特殊的語義,則該實現必須記錄這些語義。

註意,Condition 實例只是一些普通的對象,它們自身可以用作 synchronized 語句中的目標,並且可以調用自己的 waitnotification 監視器方法。獲取 Condition 實例的監視器鎖或者使用其監視器方法,與獲取和該 Condition 相關的 Lock 或使用其 waitingsignalling 方法沒有什麼特定的關係。為了避免混淆,建議除了在其自身的實現中之外,切勿以這種方式使用 Condition 實例。

除非另行說明,否則為任何參數傳遞 null 值將導致拋出 NullPointerException

實現註意事項

在等待 Condition 時,允許發生“虛假喚醒”,這通常作為對基礎平臺語義的讓步。對於大多數應用程式,這帶來的實際影響很小,因為 Condition 應該總是在一個迴圈中被等待,並測試正被等待的狀態聲明。某個實現可以隨意移除可能的虛假喚醒,但建議應用程式程式員總是假定這些虛假喚醒可能發生,因此總是在一個迴圈中等待。

三種形式的條件等待(可中斷、不可中斷和超時)在一些平臺上的實現以及它們的性能特征可能會有所不同。尤其是它可能很難提供這些特性和維護特定語義,比如排序保證。更進一步地說,中斷線程實際掛起的能力在所有平臺上並不是總是可行的。

因此,並不要求某個實現為所有三種形式的等待定義完全相同的保證或語義,也不要求其支持中斷線程的實際掛起。

要求實現清楚地記錄每個等待方法提供的語義和保證,在某個實現不支持中斷線程的掛起時,它必須遵從此介面中定義的中斷語義。

由於中斷通常意味著取消,而又通常很少進行中斷檢查,因此實現可以先於普通方法的返回來對中斷進行響應。即使出現在另一個操作後的中斷可能會釋放線程鎖時也是如此。實現應記錄此行為。

從以下版本開始:
1.5

方法摘要
 void await()
          造成當前線程在接到信號或被中斷之前一直處於等待狀態。
 boolean await(long time, TimeUnit unit)
          造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。
 long awaitNanos(long nanosTimeout)
          造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。
 void awaitUninterruptibly()
          造成當前線程在接到信號之前一直處於等待狀態。
 boolean awaitUntil(Date deadline)
          造成當前線程在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態。
 void signal()
          喚醒一個等待線程。
 void signalAll()
          喚醒所有等待線程。

 

方法詳細信息

await

void await()
           throws InterruptedException
造成當前線程在接到信號或被中斷之前一直處於等待狀態。

與此 Condition 相關的鎖以原子方式釋放,並且出於線程調度的目的,將禁用當前線程,且在發生以下四種情況之一 以前,當前線程將一直處於休眠狀態:

  • 其他某個線程調用此 Conditionsignal() 方法,並且碰巧將當前線程選為被喚醒的線程;或者
  • 其他某個線程調用此 ConditionsignalAll() 方法;或者
  • 其他某個線程中斷當前線程,且支持中斷線程的掛起;或者
  • 發生“虛假喚醒

在所有情況下,在此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖。線上程返回時,可以保證 它保持此鎖。

如果當前線程:

  • 在進入此方法時已經設置了該線程的中斷狀態;或者
  • 在支持等待和中斷線程掛起時,線程被中斷

則拋出 InterruptedException,並清除當前線程的中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

實現註意事項

假定調用此方法時,當前線程保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出響應的實現。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實現必須對此進行記錄。

與響應某個信號而返回的普通方法相比,實現可能更喜歡響應某個中斷。在這種情況下,實現必須確保信號被重定向到另一個等待線程(如果有的話)。

 

 

拋出:
InterruptedException - 如果當前線程被中斷(並且支持中斷線程掛起)

awaitUninterruptibly

void awaitUninterruptibly()
造成當前線程在接到信號之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於線程調度的目的,將禁用當前線程,且在發生以下三種情況之一 以前,當前線程將一直處於休眠狀態:

  • 其他某個線程調用此 Conditionsignal() 方法,並且碰巧將當前線程選為被喚醒的線程;或者
  • 其他某個線程調用此 ConditionsignalAll() 方法;或者
  • 發生“虛假喚醒

在所有情況下,在此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖。線上程返回時,可以保證 它保持此鎖。

如果在進入此方法時設置了當前線程的中斷狀態,或者在等待時,線程被中斷,那麼在接到信號之前,它將繼續等待。當最終從此方法返回時,仍然將設置其中斷狀態。

實現註意事項

假定調用此方法時,當前線程保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出響應的實現。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實現必須對此進行記錄。

 


awaitNanos

long awaitNanos(long nanosTimeout)
                throws InterruptedException
造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於線程調度的目的,將禁用當前線程,且在發生以下五種情況之一 以前,當前線程將一直處於休眠狀態:

  • 其他某個線程調用此 Conditionsignal() 方法,並且碰巧將當前線程選為被喚醒的線程;或者
  • 其他某個線程調用此 ConditionsignalAll() 方法;或者
  • 其他某個線程中斷當前線程,且支持中斷線程的掛起;或者
  • 已超過指定的等待時間;或者
  • 發生“虛假喚醒”。

在所有情況下,在此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖。線上程返回時,可以保證 它保持此鎖。

如果當前線程:

  • 在進入此方法時已經設置了該線程的中斷狀態;或者
  • 在支持等待和中斷線程掛起時,線程被中斷

則拋出 InterruptedException,並且清除當前線程的已中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

在返回時,該方法返回了所剩毫微秒數的一個估計值,以等待所提供的 nanosTimeout 值的時間,如果超時,則返回一個小於等於 0 的值。可以用此值來確定在等待返回但某一等待條件仍不具備的情況下,是否要再次等待,以及再次等待的時間。此方法的典型用法採用以下形式:

 synchronized boolean aMethod(long timeout, TimeUnit unit) {
   long nanosTimeout = unit.toNanos(timeout);
   while (!conditionBeingWaitedFor) {
     if (nanosTimeout > 0)
         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
      else
        return false;
   }
   // ... 
 }
 

設計註意事項:此方法需要一個 nanosecond 參數,以避免在報告剩餘時間時出現截斷錯誤。在發生重新等待時,這種精度損失使得程式員難以確保總的等待時間不少於指定等待時間。

實現註意事項

假定調用此方法時,當前線程保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出響應的實現。通常會拋出一個異常(比如 IllegalMonitorStateException)並且該實現必須對此進行記錄。

與響應某個信號而返回的普通方法相比,或者與指示所使用的指定等待時間相比,實現可能更喜歡響應某個中斷。在任意一種情況下,實現必須確保信號被重定向到另一個等待線程(如果有的話)。

 

 

參數:
nanosTimeout - 等待的最長時間,以毫微秒為單位
返回:
nanosTimeout 值減去花費在等待此方法的返回結果的時間的估算。正值可以用作對此方法進行後續調用的參數,來完成等待所需時間結束。小於等於零的值表示沒有剩餘時間。
拋出:
InterruptedException - 如果當前線程被中斷(並且支持中斷線程掛起)

await

boolean await(long time,
              TimeUnit unit)
              throws InterruptedException
造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。此方法在行為上等效於:
   awaitNanos(unit.toNanos(time)) > 0
 

 

參數:
time - 最長等待時間
unit - time 參數的時間單位
返回:
如果在從此方法返回前檢測到等待時間超時,則返回 false,否則返回 true
拋出:
InterruptedException - 如果當前線程被中斷(並且支持中斷線程掛起)

awaitUntil

boolean awaitUntil(Date deadline)
                   throws InterruptedException
造成當前線程在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於線程調度的目的,將禁用當前線程,且在發生以下五種情況之一 以前,當前線程將一直處於休眠狀態:

  • 其他某個線程調用此 Conditionsignal() 方法,並且碰巧將當前線程選為被喚醒的線程;或者
  • 其他某個線程調用此 ConditionsignalAll() 方法;或者
  • 其他某個線程中斷當前線程,且支持中斷線程的掛起;或者
  • 指定的最後期限到了;或者
  • 發生“虛假喚醒”。

在所有情況下,在此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖。線上程返回時,可以保證 它保持此鎖。

如果當前線程:

  • 在進入此方法時已經設置了該線程的中斷狀態;或者
  • 在支持等待和中斷線程掛起時,線程被中斷

則拋出 InterruptedException,並且清除當前線程的已中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

返回值指示是否到達最後期限,使用方式如下:

 synchronized boolean aMethod(Date deadline) {
   boolean stillWaiting = true;
   while (!conditionBeingWaitedFor) {
     if (stillWaiting)
         stillWaiting = theCondition.awaitUntil(deadline);
      else
        return false;
   }
   // ... 
 }
 

實現註意事項

假定調用此方法時,當前線程保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出響應的實現。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實現必須對此進行記錄。

與響應某個信號而返回的普通方法相比,或者與指示是否到達指定最終期限相比,實現可能更喜歡響應某個中斷。在任意一種情況下,實現必須確保信號被重定向到另一個等待線程(如果有的話)。

 

 

參數:
deadline - 一直處於等待狀態的絕對時間
返回:
如果在返回時已經到達最後期限,則返回 false,否則返回 true
拋出:
InterruptedException - 如果當前線程被中斷(並且支持中斷線程掛起)

signal

void signal()
喚醒一個等待線程。

如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新獲取鎖。

 


signalAll

void signalAll()
喚醒所有等待線程。

如果所有的線程都在等待此條件,則喚醒所有線程。在從 await 返回之前,每個線程都必須重新獲取鎖。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • re模塊 序言: re模塊用於對python的正則表達式的操作 標誌位即模式修正符,不改變正則表達式的情況下,通過模式修正符改變正則表達式的含義,從而實現一些匹配結果的調整等功能: 貪婪模式、懶惰模式: match: 從起始位置開始根據模型去字元串中匹配指定內容: 匹配ip地址: search: 根 ...
  • 1. 為重用以及更好的維護代碼,`Python`使用了模塊與包;一個`Python`文件就是一個模塊,包是組織模塊的特殊目錄(包含`__init__.py`文件)。 2. 模塊搜索路徑,`Python`解釋器在特定的目錄中搜索模塊,運行時`sys.path`即搜索路徑。 3. 使用`import`關... ...
  • 編譯器是怎麼實現引用類型的呢?本篇文章複習了const常量和指針,在此基礎上推測了引用類型的本質。旨在加深對語言的理解,希望對你有所幫助。 ...
  • /* 這裡要說明一下 因為本人比較懶 博客中相關文章的內容更多的是對一書中代碼的整理和簡單註解方便自己日後複習和參考, 對相關內容感興趣的初學的朋友建議請先閱讀原文。此處的內容只能當成一種學習的補充和參考。謝謝! 因原書中領域模型+數據映射器的示例代碼是連貫在一起的 所以這裡就整理在一起了。 簡單介... ...
  • jdk1.7.0_79 對於線程池大部分人可能會用,也知道為什麼用。無非就是任務需要非同步執行,再者就是線程需要統一管理起來。對於從線程池中獲取線程,大部分人可能只知道,我現在需要一個線程來執行一個任務,那我就把任務丟到線程池裡,線程池裡有空閑的線程就執行,沒有空閑的線程就等待。實際上對於線程池的執行 ...
  • 段落 非常自然,一行文字就是一個段落。 比如 這是一個段落。 會被解釋成 這是一個段落。 如果你需要另起一段,請在兩個段落之間隔一個空行。 這是一個段落。 這是另一個段落。 會解釋成 這是一個段落 這是另一個段落 不隔一個空行的換行行為,在一些編輯器中被解釋為換行,即插入一個標簽。對與另外一些編輯器 ...
  • 面試時,面試官如果想考查你機算機網路學得怎麼樣,怎麼說也得問下TCP三次握手的過程吧? so, 我4月24號就開始複習電腦網路,斷斷續續複習了3天吧。 ISP: Internet Service Provider 網際網路服務提供商 Eg: 中國電信、中國聯通和中國移動 路由器是一種專用電腦。路由 ...
  • xml文件讀取到資料庫 第一步,導包 c3p0,dom4j,jaxen,MySQL-connector 第二步 xml文件,config文件 第三步 javabean 第四步 c3p0的工具類 第五步 讀取xml文件 SAXReader中的xpath的方式 首先需要map集合添加別名,遍歷讀取到的文 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...