Java中Semaphore(信號量) 數據庫連接池

計數信號量用來控制同時訪問某個特定資源的操作數或同時執行某個指定操作的數量

A counting semaphore.Conceptually, a semaphore maintains a set of permits. Each acquire blocks if necessary until a permit is?available, and then takes it. Each release adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

從概念上來說,Semaphore中維護了一組許可,許可的數量在構造函數中指定。acquire方法將獲取一個可用的許可,如果沒有可用的許可,該方法會被阻塞,直到Semaphore中有可用的許可。release方法釋放一個許可,如果此時存在阻塞中的acqure方法,將釋放一個阻塞中的acquire

事實上,Semaphore中只維護可用請求數量,并不包含實際的請求對象

示例一:數據庫連接池

在初始化Semaphore時可以設置其公平性,如果為公平Semaphore,則按照請求時間獲得許可,即先發送的請求先獲得許可,如果為非公平Semaphore,則先發送的請求未必先獲得許可,這有助于提高程序的吞吐量,但是有可能導致某些請求始終獲取不到許可(tryAcquire方法不使用公平性設置)

[java]?view plaincopy
  1. import?java.sql.Connection;??
  2. import?java.sql.DriverManager;??
  3. import?java.util.HashMap;??
  4. import?java.util.LinkedList;??
  5. import?java.util.Map;??
  6. import?java.util.concurrent.Semaphore;??
  7. ??
  8. public?class?MyConnPool?{??
  9. ????private?LinkedList<Connection>?unusedConns?=???
  10. ????????new?LinkedList<Connection>();??
  11. ????//釋放連接時對查找性能要求較高,故使用哈希表??
  12. ????private?Map<Connection,String>?usedConns?=???
  13. ????????????new?HashMap<Connection,String>();??
  14. ????private?final?Semaphore?available;??
  15. ??????
  16. ????public?MyConnPool(int?size)?throws?Exception{??
  17. ????????StringBuilder?builder?=?new?StringBuilder();??
  18. ????????builder.append("-----pool-----\n");??
  19. ????????available?=?new?Semaphore(size,?true);//公平性Semaphore??
  20. ????????String?url?=?"jdbc:mysql://ip:port/name?user=user&password=pwd";??
  21. ????????for(int?i?=?0?;?i?<?size?;?i++){??
  22. ????????????Connection?conn?=?DriverManager.getConnection(url);??
  23. ????????????unusedConns.add(conn);??
  24. ????????????builder.append("conn-"?+?i?+?":"?+?conn.hashCode()?+?"\n");??
  25. ????????}??
  26. ????????builder.append("--------------\n");??
  27. ????????System.out.print(builder.toString());??
  28. ????}??
  29. ??????
  30. ????public?Connection?getConn()?throws?InterruptedException{??
  31. ????????//獲取Semaphore中的許可??
  32. ????????available.acquire();??
  33. ????????Connection?conn?=?null;??
  34. ????????synchronized(this){??
  35. ????????????conn?=?unusedConns.removeFirst();??
  36. ????????????usedConns.put(conn,?"");??
  37. ??????????????
  38. ????????????System.out.println(Thread.currentThread().getName()??
  39. ????????????????????+?":"?+?conn.hashCode()?+?"[got]");??
  40. ????????????System.out.println(display());??
  41. ????????}??
  42. ????????return?conn;??
  43. ????}??
  44. ??????
  45. ????public?void?close(Connection?conn){??
  46. ????????synchronized(this){??
  47. ????????????if(usedConns.containsKey(conn)){??
  48. ????????????????usedConns.remove(conn);??
  49. ????????????????unusedConns.addLast(conn);??
  50. ??????????????????
  51. ????????????????System.out.println(Thread.currentThread().getName()??
  52. ????????????????????????+?":"?+?conn.hashCode()?+?"[closed]");??
  53. ????????????????System.out.println(display());??
  54. ????????????}??
  55. ????????}??
  56. ????????//釋放線程獲取的許可??
  57. ????????available.release();??
  58. ????}??
  59. ??????
  60. ????private?final?synchronized?String?display(){??
  61. ????????String?str?=?"";??
  62. ????????if(unusedConns.size()?>?0){??
  63. ????????????str?=?"";??
  64. ????????????for(Connection?conn?:?unusedConns){??
  65. ????????????????str?+=?conn.hashCode()?+?"|";??
  66. ????????????}??
  67. ????????}??
  68. ????????if(!str.equals(""))??
  69. ????????????return?str;??
  70. ????????else??
  71. ????????????return?"empty";??
  72. ????}??
  73. }??
[java]?view plaincopy
  1. import?java.sql.Connection;??
  2. import?java.util.concurrent.CountDownLatch;??
  3. ??
  4. public?class?Test?implements?Runnable{??
  5. ????private?static?CountDownLatch?latch???
  6. ????????????=?new?CountDownLatch(1);??
  7. ????private?MyConnPool?pool;??
  8. ??????
  9. ????public?Test(MyConnPool?pool){??
  10. ????????this.pool?=?pool;??
  11. ????}??
  12. ??????
  13. ????@Override??
  14. ????public?void?run(){???
  15. ????????try?{??
  16. ????????????latch.await();??
  17. ????????????Connection?conn?=?pool.getConn();??
  18. ????????????Thread.sleep(1*1000);??
  19. ????????????pool.close(conn);??
  20. ????????}?catch?(InterruptedException?e)?{??
  21. ????????????e.printStackTrace();??
  22. ????????}??
  23. ????}??
  24. ??????
  25. ????public?static?void?main(String[]?args)?throws?Exception{??
  26. ????????MyConnPool?pool?=?new?MyConnPool(2);??
  27. ????????for(int?i?=?0?;?i?<?4?;?i++){??
  28. ????????????Thread?t?=?new?Thread(new?Test(pool));??
  29. ????????????t.start();??
  30. ????????}??
  31. ????????//保證4個線程同時運行??
  32. ????????latch.countDown();??
  33. ????}??
  34. }??

運行結果如下:

[plain]?view plaincopy
  1. -----pool-----??
  2. conn-0:11631043??
  3. conn-1:14872264??
  4. --------------??
  5. Thread-4:11631043[got]??
  6. 14872264|??
  7. Thread-1:14872264[got]??
  8. empty??
  9. Thread-4:11631043[closed]??
  10. 11631043|??
  11. Thread-2:11631043[got]??
  12. empty??
  13. Thread-1:14872264[closed]??
  14. 14872264|??
  15. Thread-3:14872264[got]??
  16. empty??
  17. Thread-2:11631043[closed]??
  18. 11631043|??
  19. Thread-3:14872264[closed]??
  20. 11631043|14872264|??

特別注意如果getConn方法和close方法都為同步方法,將產生死鎖:

[java]?view plaincopy
  1. public?synchronized?Connection?getConn()?throws?InterruptedException{??
  2. ????......??
  3. }??
  4. ??????
  5. public?synchronized?void?close(Connection?conn){??
  6. ????......??
  7. }??

同一時刻只能有一個線程調用連接池的getConn方法或close方法,當Semaphore中沒有可用的許可,并且此時恰好有一個線程成功調用連接池的getConn方法,則該線程將一直阻塞在acquire方法上,其它線程將沒有辦法獲取連接池上的鎖并調用close方法釋放許可,程序將會卡死

阻塞方法上不要加鎖,否則將導致鎖長時間不釋放,如果該鎖為互斥鎖,將導致程序卡住

acquire方法本身使用樂觀鎖實現,也不需要再加互斥鎖

示例二:不可重入互斥鎖

[java]?view plaincopy
  1. import?java.util.concurrent.CountDownLatch;??
  2. import?java.util.concurrent.Semaphore;??
  3. ??
  4. public?class?Test?implements?Runnable{??
  5. ????private?static?CountDownLatch?latch?=??
  6. ????????????new?CountDownLatch(1);??
  7. ????private?static?Semaphore?lock?=??
  8. ????????????new?Semaphore(1,?true);??
  9. ??????
  10. ????@Override??
  11. ????public?void?run(){???
  12. ????????try?{??
  13. ????????????latch.await();??
  14. ????????????this.work();??
  15. ????????}?catch?(InterruptedException?e)?{??
  16. ????????????e.printStackTrace();??
  17. ????????}??
  18. ????}??
  19. ??????
  20. ????private?void?work()?throws?InterruptedException{??
  21. ????????????lock.acquire();??
  22. ????????????System.out.println("Locking?by?"???
  23. ????????????????????+?Thread.currentThread().getName());??
  24. ????????????Thread.sleep(1*1000);??
  25. ????????????lock.release();??
  26. ????}??
  27. ??????
  28. ????public?static?void?main(String[]?args)?throws?Exception{??
  29. ????????for(int?i?=?0?;?i?<?4?;?i++){??
  30. ????????????Thread?t?=?new?Thread(new?Test());??
  31. ????????????t.start();??
  32. ????????}??
  33. ????????//保證4個線程同時運行??
  34. ????????latch.countDown();??
  35. ????}??
  36. }??

運行結果如下:

[plain]?view plaincopy
  1. Locking?by?Thread-3??
  2. Locking?by?Thread-0??
  3. Locking?by?Thread-1??
  4. Locking?by?Thread-2??

?

轉載于:https://www.cnblogs.com/jiangzhaowei/p/7221208.html

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

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

相關文章

Visual Studio for Mac Preview離線下載安裝

Visual Studio for Mac離線下載安裝。 環境&#xff1a;OS X EI Caption 10.11.2 .NET Core SDK 1.1 需預先安裝 .NET Core 1.1 SDK macOS版下載地址:https://go.microsoft.com/fwlink/?LinkID835011 安裝SDK需先安裝openssl。 brew update brew install openssl mkdir -p /us…

LOAM_velodyne學習(一)

在研讀了論文及開源代碼后&#xff0c;對LOAM的一些理解做一個整理。 文章&#xff1a;Low-drift and real-time lidar odometry and mapping 開源代碼&#xff1a;https://github.com/daobilige-su/loam_velodyne 系統概述 LOAM的整體思想就是將復雜的SLAM問題分為&#x…

實戰Vue簡易項目(2)定制開發環境

本章內容包含上一章思考的解決&#xff0c;還有一些其它的定制... CSS預處理 關于對.vue文件模塊處理規則的配置依次可在build/webpack.base.conf.js->build/vue-loader.conf.js->build/utils.js文件中跟蹤&#xff1b; 而loaders的關鍵在于build/vue-loader.conf.js文件…

LINUX framebuffer

http://wangshh03.blog.163.com/blog/static/49103415201001231317484/ 一、FrameBuffer的原理 FrameBuffer 是出現在 2.2.xx 內核當中的一種驅動程序接口。 Linux是工作在保護模式下&#xff0c;所以用戶態進程是無法象DOS那樣使用顯卡BIOS里提供的中斷調用來實現直接寫屏&…

[POI2007]POW-The Flood

題目描述 給定一張地勢圖&#xff0c;所有的點都被水淹沒&#xff0c;現在有一些關鍵點&#xff0c;要求放最少的水泵使所有關鍵點的水都被抽干 輸入輸出格式 輸入格式&#xff1a; In the first line of the standard input there are two integers and , separated by a sin…

LOAM_velodyne學習(二)

LaserOdometry 這一模塊&#xff08;節點&#xff09;主要功能是&#xff1a;進行點云數據配準&#xff0c;完成運動估計 利用ScanRegistration中提取到的特征點&#xff0c;建立相鄰時間點云數據之間的關聯&#xff0c;由此推斷lidar的運動。我們依舊從主函數開始&#xff1…

戶外穿越

晚上很早就睡了&#xff0c;并且&#xff0c;太過激動&#xff0c;所以早上四點五十分就被驚醒&#xff0c;然后到早上鬧鐘響。 早上匆匆忙吃過早餐&#xff0c;就趕去坐車&#xff0c;到登山之前&#xff0c;坐了大巴車&#xff0c;又坐了景區的車&#xff0c;景區的路是山路十…

【oracle】關于創建表時用default指定默認值的坑

剛開始學create table的時候沒注意&#xff0c;學到后面發現可以指定默認值。于是寫了如下語句&#xff1a; 當我查詢的時候發現&#xff0c;查出來的結果是這樣的。。 很納悶有沒有&#xff0c;我明明指定默認值了呀&#xff0c;為什么創建出來的表還是空的呢&#xff1f;又跑…

Makefile中用宏定義進行條件編譯(gcc -D)/在Makefile中進行宏定義-D

在源代碼里面如果這樣是定義的&#xff1a; #ifdef MACRONAME //可選代碼 #endif 那在makefile里面 gcc -D MACRONAMEMACRODEF 或者 gcc -D MACRONAME 這樣就定義了預處理宏&#xff0c;編譯的時候可選代碼就會被編譯進去了。 對于GCC編譯器&#xff0c;有如下選項&…

python安裝與配置

首先下載python地址&#xff1a; https://www.python.org/downloads/release/python-361/下載頁面中有多個版本&#xff1a; web-based installer 是需要通過聯網完成安裝的 executable installer 是可執行文件(*.exe)方式安裝 embeddable zip file 嵌入式版本&#xff0c;可…

[OpenGL ES 03]3D變換:模型,視圖,投影與Viewport

[OpenGL ES 03]3D變換&#xff1a;模型&#xff0c;視圖&#xff0c;投影與Viewport 羅朝輝 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商業用途-保持一致”創作公用協議 系列文章&#xff1a;[OpenGL ES 01]OpenGL ES之初體驗[OpenGL ES 02]OpenGL ES渲染管線與著色器…

LOAM_velodyne學習(三)

終于到第三個模塊了&#xff0c;我們先來回顧下之前的工作&#xff1a;點云數據進來后&#xff0c;經過前兩個節點的處理可以完成一個完整但粗糙的里程計&#xff0c;可以概略地估計出Lidar的相對運動。如果不受任何測量噪聲的影響&#xff0c;這個運動估計的結果足夠精確&…

監控視頻線種類 視頻信號傳輸介紹及各種視頻接口的傳輸距離

一.視頻信號接口 監控視頻線種類介紹&#xff1a; 按照材料區分有SYV及SYWV兩種&#xff0c;絕緣層的物理材料結構不同&#xff0c;SYV是實心聚乙烯電纜&#xff0c;SYWV是高物理發泡電纜&#xff0c;物理發泡電纜傳輸性能優于聚乙烯。 S--同軸電纜 Y--聚乙烯 V--聚氯乙烯 W…

免費節假日API 更新新功能了 新增農歷信息返回

感謝大家對免費節假日API的支持.最近看了別家的api于是增加了一些新功能即獲取日期的農歷信息. 這個新功能還處于測試階段如有問題歡迎反饋 檢查一個日期是詳細信息 https://tool.bitefu.net/jiari/?d20180101&info1 返回值 {"status": 1,"type": 1,…

新手算法學習之路----二叉樹(二叉樹最大路徑和)

摘抄自&#xff1a;https://segmentfault.com/a/1190000003554858#articleHeader2 題目&#xff1a; Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. For example: Given the below binary tree, 1/ \2 3Return 6. 思…

Ajax工作原理

詳見&#xff1a;http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt238 在這篇文章中&#xff0c;我將從10個方面來對AJAX技術進行系統的講解。 1、ajax技術的背景 不可否認&#xff0c;ajax技術的流行得益于google的大力推廣&#xff0c;正是由于google earth、go…

各種視頻信號格式及端子介紹/VGA DVI HDMI區別

視頻信號是我們接觸最多的顯示信號&#xff0c;但您并不一定對各種視頻信號有所了解。因為國內用到的視頻信號格式和端子非常有限&#xff0c;一般就是復合視頻和S端子&#xff0c;稍高級一些的就是色差及VGA。對于那些經常接觸國外電器和二手設備的朋友&#xff0c;就會遇到各…

LOAM_velodyne學習(四)

TransformMaintenance 來到了最后一個模塊&#xff0c;代碼不是很長&#xff0c;我們在看完代碼之后&#xff0c;再詳細說明這個模塊的功能 依然主函數開始 int main(int argc, char** argv) {ros::init(argc, argv, "transformMaintenance");ros::NodeHandle nh;…

PHP數據庫類

<?phpclass Db{//私有靜態屬性存儲實例化對象自身private static $instance;//存儲PDO類的實例化private $pdo;//PDOStatement類private $stmt;//禁止外部實例化對象&#xff0c;鏈接數據庫private function __construct($config,$port,$charset){try{$this->pdo new P…

oracle參數文件、控制文件、數據文件、日志文件的位置及查詢方法

參數文件&#xff1a;所有參數文件一般在 $ORACLE_HOME/dbs 下 sqlplus查詢語句&#xff1a;show parameter spfile; 網絡連接文件&#xff1a; $ORACLE_HOME/dbs/network/admin 目錄中 控制文件&#xff1a;select * from v$controlfile; 數據文件&#xff1a;一般在oracleda…