摘要:池化技術(shù)簡介在我們使用數(shù)據(jù)庫的過程中,我們往往使用數(shù)據(jù)庫連接池而不是直接使用數(shù)據(jù)庫連接進行操作,這是因為每一個數(shù)據(jù)庫連接的創(chuàng)建和銷毀的代價是昂貴的,而池化技術(shù)則預(yù)先創(chuàng)建了資源,這些資源是可復用的這樣就保證了在多用戶情況下只能使用指定數(shù)目的資
池化技術(shù)簡介
在我們使用數(shù)據(jù)庫的過程中,我們往往使用數(shù)據(jù)庫連接池而不是直接使用數(shù)據(jù)庫連接進行操作,這是因為每一個數(shù)據(jù)庫連接的創(chuàng)建和銷毀的代價是昂貴的,而池化技術(shù)則預(yù)先創(chuàng)建了資源,這些資源是可復用的,這樣就保證了在多用戶情況下只能使用指定數(shù)目的資源,避免了一個用戶創(chuàng)建一個連接資源,造成程序運行開銷過大。
連接池實現(xiàn)原理這里只實現(xiàn)一個簡易的連接池,更多復雜的需求可根據(jù)該連接池進行改進,該連接池主要參數(shù)如下:
一個繁忙隊列busy
一個空閑隊列idle
連接池最大活動連接數(shù)maxActive
連接池最大等待時間maxWait
連接池的活動連接數(shù)activeSize
程序流程圖如下:
泛型接口ConnectionPool.java
public interface ConnectionPool{ /** * 初始化池資源 * @param maxActive 池中最大活動連接數(shù) * @param maxWait 最大等待時間 */ void init(Integer maxActive, Long maxWait); /** * 從池中獲取資源 * @return 連接資源 */ T getResource() throws Exception; /** * 釋放連接 * @param connection 正在使用的連接 */ void release(T connection) throws Exception; /** * 釋放連接池資源 */ void close(); }
以zookeeper為例,實現(xiàn)zookeeper連接池,ZookeeperConnectionPool.java
public class ZookeeperConnectionPool implements ConnectionPool測試用例{ //最大活動連接數(shù) private Integer maxActive; //最大等待時間 private Long maxWait; //空閑隊列 private LinkedBlockingQueue idle = new LinkedBlockingQueue<>(); //繁忙隊列 private LinkedBlockingQueue busy = new LinkedBlockingQueue<>(); //連接池活動連接數(shù) private AtomicInteger activeSize = new AtomicInteger(0); //連接池關(guān)閉標記 private AtomicBoolean isClosed = new AtomicBoolean(false); //總共獲取的連接記數(shù) private AtomicInteger createCount = new AtomicInteger(0); //等待zookeeper客戶端創(chuàng)建完成的計數(shù)器 private static ThreadLocal latchThreadLocal = ThreadLocal.withInitial(() -> new CountDownLatch(1)); public ZookeeperConnectionPool(Integer maxActive, Long maxWait) { this.init(maxActive, maxWait); } @Override public void init(Integer maxActive, Long maxWait) { this.maxActive = maxActive; this.maxWait = maxWait; } @Override public ZooKeeper getResource() throws Exception { ZooKeeper zooKeeper; Long nowTime = System.currentTimeMillis(); final CountDownLatch countDownLatch = latchThreadLocal.get(); //空閑隊列idle是否有連接 if ((zooKeeper = idle.poll()) == null) { //判斷池中連接數(shù)是否小于maxActive if (activeSize.get() < maxActive) { //先增加池中連接數(shù)后判斷是否小于等于maxActive if (activeSize.incrementAndGet() <= maxActive) { //創(chuàng)建zookeeper連接 zooKeeper = new ZooKeeper("localhost", 5000, (watch) -> { if (watch.getState() == Watcher.Event.KeeperState.SyncConnected) { countDownLatch.countDown(); } }); countDownLatch.await(); System.out.println("Thread:" + Thread.currentThread().getId() + "獲取連接:" + createCount.incrementAndGet() + "條"); busy.offer(zooKeeper); return zooKeeper; } else { //如增加后發(fā)現(xiàn)大于maxActive則減去增加的 activeSize.decrementAndGet(); } } //若活動線程已滿則等待busy隊列釋放連接 try { System.out.println("Thread:" + Thread.currentThread().getId() + "等待獲取空閑資源"); Long waitTime = maxWait - (System.currentTimeMillis() - nowTime); zooKeeper = idle.poll(waitTime, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new Exception("等待異常"); } //判斷是否超時 if (zooKeeper != null) { System.out.println("Thread:" + Thread.currentThread().getId() + "獲取連接:" + createCount.incrementAndGet() + "條"); busy.offer(zooKeeper); return zooKeeper; } else { System.out.println("Thread:" + Thread.currentThread().getId() + "獲取連接超時,請重試!"); throw new Exception("Thread:" + Thread.currentThread().getId() + "獲取連接超時,請重試!"); } } //空閑隊列有連接,直接返回 busy.offer(zooKeeper); return zooKeeper; } @Override public void release(ZooKeeper connection) throws Exception { if (connection == null) { System.out.println("connection 為空"); return; } if (busy.remove(connection)){ idle.offer(connection); } else { activeSize.decrementAndGet(); throw new Exception("釋放失敗"); } } @Override public void close() { if (isClosed.compareAndSet(false, true)) { idle.forEach((zooKeeper) -> { try { zooKeeper.close(); } catch (InterruptedException e) { e.printStackTrace(); } }); busy.forEach((zooKeeper) -> { try { zooKeeper.close(); } catch (InterruptedException e) { e.printStackTrace(); } }); } } }
這里創(chuàng)建20個線程并發(fā)測試連接池,Test.java
public class Test { public static void main(String[] args) throws Exception { int threadCount = 20; Integer maxActive = 10; Long maxWait = 10000L; ZookeeperConnectionPool pool = new ZookeeperConnectionPool(maxActive, maxWait); CountDownLatch countDownLatch = new CountDownLatch(20); for (int i = 0; i < threadCount; i++) { new Thread(() -> { countDownLatch.countDown(); try { countDownLatch.await(); ZooKeeper zooKeeper = pool.getResource(); Thread.sleep(2000); pool.release(zooKeeper); } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }).start(); } while (true){ } } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73054.html
摘要:純分享直接上干貨操作系統(tǒng)并發(fā)支持進程管理內(nèi)存管理文件系統(tǒng)系統(tǒng)進程間通信網(wǎng)絡(luò)通信阻塞隊列數(shù)組有界隊列鏈表無界隊列優(yōu)先級有限無界隊列延時無界隊列同步隊列隊列內(nèi)存模型線程通信機制內(nèi)存共享消息傳遞內(nèi)存模型順序一致性指令重排序原則內(nèi)存語義線程 純分享 , 直接上干貨! 操作系統(tǒng)并發(fā)支持 進程管理內(nèi)存管...
摘要:從使用到原理學習線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:所以得出結(jié)論需要分配較多的線程進行讀數(shù)據(jù),較少的線程進行寫數(shù)據(jù)。注意多線程編程對實際環(huán)境和需求有很大的依賴,需要根據(jù)實際的需求情況對各個參數(shù)做調(diào)整。 背景 最近對于 Java 多線程做了一段時間的學習,筆者一直認為,學習東西就是要應(yīng)用到實際的業(yè)務(wù)需求中的。否則要么無法深入理解,要么硬生生地套用技術(shù)只是達到炫技的效果。 不過筆者仍舊認為自己對于多線程掌握不夠熟練,不敢輕易應(yīng)用到生產(chǎn)代碼中...
閱讀 930·2021-10-27 14:14
閱讀 1753·2021-10-11 10:59
閱讀 1325·2019-08-30 13:13
閱讀 3160·2019-08-29 15:17
閱讀 2759·2019-08-29 13:48
閱讀 498·2019-08-26 13:36
閱讀 2090·2019-08-26 13:25
閱讀 866·2019-08-26 12:24