Java并發教程–信號量

這是我們將要進行的Java并發系列的第一部分。 具體來說,我們將深入探討Java 1.5及更高版本中內置的并發工具。 我們假設您對同步和易失性關鍵字有基本的了解。

第一篇文章將介紹信號量-特別是對信號量進行計數 。 信號量是用于限制對資源訪問的經常被誤解和使用不足的工具。 對于其他控制對資源的訪問的方式,它們將被忽略。 但是信號量為我們提供了一個超越常規同步和其他工具所能提供的工具集的工具集。

那么什么是信號量? 想到信號量的最簡單方法是將其視為允許n個單位被獲取并提供獲取和釋放機制的抽象。 它安全地允許我們確保在給定的時間只有n個進程可以訪問特定資源

一切都很好,但是這將達到什么目的呢? 好吧,這是一個示例,將有助于解釋其用法。 它使用位于1.5。中的java.util.concurrent包中精心設計的Semaphore類。

限制連接

也許我們有一個過程可以通過HTTP定期為我們下載資源。 我們不想向任何主機發送垃圾郵件,同時,我們想限制正在建立的連接數,因此我們不會耗盡允許的有限文件句柄或出站連接。 一種簡單的方法是使用信號量:

public class ConnectionLimiter {private final Semaphore semaphore;private ConnectionLimiter(int maxConcurrentRequests) {semaphore = new Semaphore(maxConcurrentRequests);}public URLConnection acquire(URL url) throws InterruptedException,IOException {semaphore.acquire();return url.openConnection();}public void release(URLConnection conn) {try {/** ... clean up here*/} finally {semaphore.release();}}
}

對于資源有限的問題,這是一個很好的解決方案。 對acquire()的調用將阻塞,直到獲得許可為止。 信號燈的優點在于,它隱藏了管理訪問控制,計算許可數以及確保正確的線程安全性的所有復雜性。

危險性

與大多數鎖定或同步方法一樣,存在一些潛在問題。

要記住的第一件事是, 始終釋放您獲得的東西 。 這是通過使用try..finally構造完成的。

使用信號量時,還有其他不太明顯的問題可能會降臨您。 以下課程顯示了死鎖,只有您中最幸運的人才能避免。 您會注意到,獲得兩個信號量許可的兩個線程的執行順序相反。 (為簡潔起見,try..finally最終被省去了)。

public static void main(String[] args) throws Exception {Semaphore s1 = new Semaphore(1);Semaphore s2 = new Semaphore(1);Thread t = new Thread(new DoubleResourceGrabber(s1, s2));// now reverse them ... here comes trouble!Thread t2 = new Thread(new DoubleResourceGrabber(s2, s1));t.start();t2.start();t.join();t2.join();System.out.println("We got lucky!");
}private static class DoubleResourceGrabber implements Runnable {private Semaphore first;private Semaphore second;public DoubleResourceGrabber(Semaphore s1, Semaphore s2) {first = s1;second = s2;}public void run() {try {Thread t = Thread.currentThread();first.acquire();System.out.println(t + " acquired " + first);Thread.sleep(200); // demonstrate deadlocksecond.acquire();System.out.println(t + " acquired " + second);second.release();System.out.println(t + " released " + second);first.release();System.out.println(t + " released " + first);} catch (InterruptedException ex) {ex.printStackTrace();}}
}

如果運行此程序,則很有可能會掛起一個進程。 鎖排序的問題與Java中的常規互斥鎖或同步一樣,也適用于信號量。 在某些情況下,超時(請參閱本文后面的tryAcquire()注釋)可用于防止死鎖導致進程掛起,但是死鎖通常是可以避免的邏輯錯誤的征兆。 如果您不熟悉死鎖,建議您仔細閱讀它們。 維基百科上有一篇關于死鎖的文章,該文章同樣適用于所有語言。

使用信號量(包括二進制信號量,即互斥體)時應注意的主要事項是:

  • 獲取后不釋放(丟失的釋放調用或引發異常并且沒有finally塊)
  • 長時間保持信號量,導致線程饑餓
  • 死鎖(如上所示)

有用的信號燈技巧

Java中Semaphores的一個有趣的特性是, 不必通過與Acquisition相同的線程來調用release 。 這意味著您可以具有一個線程限制器,該線程限制器可以通過調用acquire()來基于信號量池或創建線程。 然后,正在運行的線程可以在完成時釋放其自己的信號燈許可。 這是Java中普通互斥鎖所沒有的有用屬性。

另一個技巧是在運行時增加許可數量 。 與您可能會猜到的相反,信號量中的許可數量不是固定的,并且即使未進行相應的acquire()調用,對release()的調用也會始終增加許可的數量。 請注意,如果在沒有進行acquire()的情況下錯誤地調用release() ,這也會導致錯誤。

最后,在Java的Semaphore中有一些有用的方法要熟悉。 方法AcquireInterruptible()將獲取資源,如果資源被中斷,則重新嘗試。 這意味著沒有對InterruptedException的外部處理。 tryAcquire()方法允許我們限制等待許可的時間-我們可以在沒有許可的情況下立即返回,也可以等待指定的超時時間。 如果您以某種方式知道了無法輕松修復或跟蹤的死鎖,則可以通過使用帶有適當超時的tryAcquire()來幫助防止鎖定進程。

用途

計數信號量有哪些可能的用途? 請注意以下幾點:

  • 限制對磁盤的并發訪問(由于競爭磁盤搜尋,這可能會降低性能)
  • 線程創建限制
  • JDBC連接池/限制
  • 網絡連接限制
  • 限制CPU或內存密集型任務

當然,信號量是訪問控制和同步的一個很底層的構建塊。 Java為我們提供了Java 1.5及更高版本中引入的大量并發機制和策略。 在接下來的文章中,我們將介紹一些更抽象的并發管理方法,包括執行器,BlockingQueues,Barriers,Future以及一些新的并發Collection類。

您發現信號量有什么用途? 通過發表評論讓我們知道–我們喜歡語音軟件。

參考: Java并發第1部分–來自我們的JCG合作伙伴的信號燈 ,在Carfey Software博客上 。

相關文章 :
  • Java并發教程–重入鎖
  • Java并發教程–線程池
  • Java并發教程–可調用,將來
  • Java并發教程–阻塞隊列
  • Java并發教程– CountDownLatch
  • Exchanger和無GC的Java
  • Java Fork / Join進行并行編程
  • Java最佳實踐–隊列之戰和鏈接的ConcurrentHashMap
  • 如何在不到1ms的延遲內完成100K TPS
  • 使用迭代器時如何避免ConcurrentModificationException
  • 改善Java應用程序性能的快速技巧
相關片段:
  • 阻塞隊列示例以執行命令
  • 限制URL連接的信號量示例
  • 執行命令的同步隊列示例
  • 更一般的等待/通知機制的CountDownLatch示例

翻譯自: https://www.javacodegeeks.com/2011/09/java-concurrency-tutorial-semaphores.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374187.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374187.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android surfaceview 大小_Android 使用Camera2 API采集視頻數據

Android 視頻數據采集系列的最后一篇出爐了,和前兩篇文章想比,這篇文章從系統API層面進行一些探索,涉及到的細節更多。初次接觸 Camera2 API 會覺得它的使用有些繁瑣,涉及到的類有些多,不過就像第一次使用Activity, Fr…

java生成隨機字符串

學習java comparable特性時候,定義如下Student類,需要需要隨機添加學生姓名以及學號和成績,這是java如何隨機生成名字,根據我的查詢,我找到目前java庫支持兩種方法。 1. org.apache.commons.lang3.RandomStringUtils類…

使用SharedPreferenes存取數據

//使用SharedPreference存儲數據 public void on(View view){     //獲取用戶名和密碼     String nameeditText1.getText().toString();     String numbereditText2.getText().toString();     //判斷checkBox是否為勾選      CheckBox box(CheckBox…

使用Java VisualVM分析您的應用程序

當您需要發現應用程序的哪個部分消耗更多的CPU或內存時,必須使用探查器執行此操作。 默認情況下,Sun JDK中附帶的一個探查器是Java VisualVM。 這個事件探查器非常簡單易用,功能強大。 在這篇文章中,我們將看到如何安裝它并使用它…

ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接

ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接 原文:ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接安裝ArcSDE for SQL Server,最后一步成功后的界面如下:在ArcMap中創建ArcSDE連接,截圖如下:posted on 2016-08-0…

java反射main方法參數注意

public class ReflectMethodMain {public static void main(String[] args) throws Exception {Method methodMainTestArgument.class.getMethod("main", String[].class);/*jdk 1.4之前的版本不支持可變參數,對組類的參數會自動拆包然后用來匹配數據參數…

python調用c函數傳字符串參數_Python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數...

在Python語言中,可以使用ctypes模塊調用其它如C語言編寫的動態鏈接庫DLL文件中的函數,在提高軟件運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟件的功能及應用領域,減少重復編寫代碼、…

沁恒CH554 KEIL環境搭建

首先下載WCHISPTool_Setup.exe http://www.wch.cn/products/CH554.html 123這三個可下載的都下吧,后面開發都要用的 安裝好后運行,菜單欄上,功能->添加WCH MCU到KEIL器件庫 這時候在KEIL安裝目錄里面的UV4文件夾下可以看到wch.cdb的文件…

【CV論文閱讀】Rank Pooling for Action Recognition

這是期刊論文的版本,不是會議論文的版本。看了論文之后,只能說,太TM聰明了。膜拜~~ 視頻的表示方法有很多,一般是把它看作幀的序列。論文提出一種新的方法去表示視頻,用ranking function的參數編碼視頻的幀序列。它使用…

java不要在常量和變量中出現易混淆的字母

public class proposal {public static void main(String[] args) {long i1l; System.out.println("i的兩倍是:"(ii));System.out.println("i的兩倍是:"ii); //注意此處和上面的有很大的區別} }輸出:211/** 注意:* …

VS2019 WPF制作OTA上位機(一)新建工程

首先創建新項目,文件 -> 新建 -> 項目 下拉菜單選擇C#和Window,選擇WPF應用程序,下一步 輸入項目名,下一步 這里選擇.NET 5.0,也可以選擇其他的,個人習慣.NET,點擊創建 這時候出現初始…

戶籍恢復需要體檢嗎_腦梗死后腳麻能恢復嗎?需要多久能恢復呢?

腦梗死之后腳部麻木,這個有一部分是能夠恢復的,但是相對而言,恢復的時間比較長,在臨床當中出現腳麻主要是因為梗死破壞了患者的感覺神經中樞從而造成。腳部感覺麻木,瘙癢或者是有螞蟻在上面爬的感覺。而且有的更加嚴重…

Alpha版本測試報告

一、測試計劃 Alpha版本即將發布,我們組織隊員進行這一版本的測試。 測試主要針對兩方面:瀏覽器兼容性和功能完善性。 測試分兼容性測試與功能完善性兩部分,兼容性測試分Windows操作系統、Linux系操作系統、Mac OS X操作系統以及手機端Androi…

在J2SE應用程序中模擬CDI的會話和請求范圍

我們目前正在考慮將Naked Objects框架重構為使用JSR-330(依賴注入)和面向EE的老大哥JSR-299(CDI)。 使用香草JSR-330是不費吹灰之力的,但是我們想利用JSR-299中的一些不錯的功能(例如事件和裝飾器&#xff…

VS2019 WPF制作OTA上位機(二)獲取bin文件路徑

OTA升級是通過無線通信遠程把bin文件內容傳輸到單片機,完成升級。 因此上位機需要獲取bin文件的路徑,讀取bin文件內容,將內容分割依次發送(因為單片機的接收緩存不會開得和bin文件一樣大(十幾K甚至幾十K)&a…

java 線程“生產/消費”模型1

/*資源類*/ public class ShareValue {private int total;public ShareValue(int total){this.totaltotal;}//生產void putValue(int value){totalvalue;}//消費資源int getValue(int value){if(total-value>0){total-value;}else{valuetotal;total0;System.out.println(&qu…

PHP - 代碼分離

總代碼&#xff1a; <?php/** Version&#xff1a;1.0* CreateTime&#xff1a;2015年11月11日* Author&#xff1a;HF_Ultrastrong*///引入公共文件,在公共文件中創建&#xff0c;相對于項目的絕對路徑require dirname(__FILE__)./includes/common.inc.php; ?&…

原生js封裝table表格操作,獲取任意行列td,任意單行單列方法

V1.001更新增加findTable-min.js 本次更新&#xff0c;優化了代碼性能方面&#xff0c;增加了部分新功能&#xff0c;可以獲取多個table表格批量操作。 考慮到本人后面的項目中可能涉及到大量的表格操作&#xff0c;提前先封了 一個簡單的操作方法&#xff0c;日后再加完善&…

Spring陷阱:事務測試被認為是有害的

Spring殺手級功能之一是容器內集成測試 。 盡管EJB多年來一直缺乏此功能&#xff08;Java EE 6終于解決了這個問題&#xff0c;但是我還沒測試過&#xff09;&#xff0c;但是Spring從一開始就允許您從Web層開始&#xff0c;通過所有服務來測試整個堆棧。到數據庫的方式。 數據…

python xlwt寫入已有表_Python中,添加寫入數據到已經存在的Excel文件

1.安裝xlrd、xlwt、xlutilshttps://pypi.org/project/xlutils/pip安裝&#xff1a;cmd下輸入&#xff1a;pip install xlrd #讀取exclepip install xlwt #寫入exclepip install xlutils #操作 Excel 文件的實用工具&#xff0c;如復制、分割、篩選等2.代碼主要部分實現import x…