簡體   English   中英

在Java中沒有旋轉的塊?

[英]Block without spinning in Java?

Java中的某些方法會阻塞,直到它們可以執行某些操作,比如ServerSocket.accept()和InputStream.read(),但是它如何做到這一點對我來說並不容易找到。 我能想到的最接近的事情是每次循環使用Thread.sleep()的while()循環,但是睡眠時間越長,阻塞響應越少,睡眠越短,發生的旋轉越多。

我有兩個問題:

  1. 各種標准功能(如上所述)如何阻止? 原生代碼? while()循環? 別的什么?

  2. 我該如何實現阻止的方法?

由於底層平台(即本機代碼),您列出的操作會被阻止。

您可以使用Java的Object.wait()Object.notify()方法實現一個塊; wait()將阻塞調用線程,直到另一個線程在同一個鎖上調用notify()

(1)的基本答案是“不要擔心它 - 操作系統處理它”。 調用從輸入流中讀取的內容實際上是圍繞操作系統調用的包裝。 在操作系統內部,我認為通常在這些情況下調用“阻塞”時,操作系統“知道”它正在等待硬盤中斷,比如磁盤控制器說這樣 - 和 - 這些請求的數據現在可用,並且它知道線程X是請求該數據的數據。 因此它不會再次在線程X中進行調度,直到它收到該中斷(或中斷說“有錯誤”等)。 (然后,線程調度算法的一部分就是在等待的數據變得可用時給等待線程一個臨時的“提升”。同樣,通常你不需要太擔心這個。)或者換一種方式:無論這種機制的確切細節如何,一般的Java程序員都無法使用它。

在(2)中,我建議更多地思考“我怎么做可能碰巧阻止的事物X”。 我認為答案幾乎沒有“你想要做的事情”故意只是“阻止”,而無論Thing X是什么,都可能有一個庫方法/類會為你做。 例如(鏈接包括我在這些主題上撰寫的一些材料):

  • 如果要在某個隊列/提供者可用時獲取下一個消息/作業,請查看阻塞隊列
  • 如果您需要通過對象上的“鎖定”來控制對共享資源的訪問,則在必要時等待鎖可用,請考慮使用普通舊同步或顯式鎖定 ;
  • 如果您想等待許多池化資源中的一個可用,請查看信號量

我會說原始等待/通知機制在很大程度上已經被Java 5並發API所棄用了。 無論你做什么,自旋鎖通常是最后的手段。

要回答(2)你想要Object方法wait,notify和notifyAll。

使用Object.wait()時,必須將wait括在一個循環中,該循環檢查您正在等待的條件。 wait()方法可以虛假返回(出於微妙的原因)。

此外,您需要考慮是否需要使用notify()或notifyAll() - 如果所有等待的線程都在等待完全相同的條件,並且您只需要一個處理您通知的任何內容,可以使用notify(),否則你需要使用notifyAll(),因為你不能保證在notify()上會通知哪個線程 - 例如,你不能指望它們是循環的。

最后,請確保您查看java.util.concurrent包 - 與使用Java原語相比,它具有許多更高級別和更好的解決常見線程問題的解決方案。

我可以回答第1部分。他們使用操作系統來處理它,因為每個操作系統已經具有內置的信令和阻塞作為啟用多任務的一部分。

通常,如果您必須實現自己的旋轉鎖定代碼,那么要么使用錯誤的方法。 旋轉還可以減少任何形式的電源管理,即使在良好的睡眠狀態下,代碼仍然必須喚醒無所事事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM