成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

java并發(fā)實(shí)戰(zhàn):連接池實(shí)現(xiàn)

XboxYan / 855人閱讀

摘要:池化技術(shù)簡介在我們使用數(shù)據(jù)庫的過程中,我們往往使用數(shù)據(jù)庫連接池而不是直接使用數(shù)據(jù)庫連接進(jìn)行操作,這是因?yàn)槊恳粋€(gè)數(shù)據(jù)庫連接的創(chuàng)建和銷毀的代價(jià)是昂貴的,而池化技術(shù)則預(yù)先創(chuàng)建了資源,這些資源是可復(fù)用的這樣就保證了在多用戶情況下只能使用指定數(shù)目的資

池化技術(shù)簡介

在我們使用數(shù)據(jù)庫的過程中,我們往往使用數(shù)據(jù)庫連接池而不是直接使用數(shù)據(jù)庫連接進(jìn)行操作,這是因?yàn)槊恳粋€(gè)數(shù)據(jù)庫連接的創(chuàng)建和銷毀的代價(jià)是昂貴的,而池化技術(shù)則預(yù)先創(chuàng)建了資源,這些資源是可復(fù)用的,這樣就保證了在多用戶情況下只能使用指定數(shù)目的資源,避免了一個(gè)用戶創(chuàng)建一個(gè)連接資源,造成程序運(yùn)行開銷過大。

連接池實(shí)現(xiàn)原理

這里只實(shí)現(xiàn)一個(gè)簡易的連接池,更多復(fù)雜的需求可根據(jù)該連接池進(jìn)行改進(jìn),該連接池主要參數(shù)如下:

一個(gè)繁忙隊(duì)列busy

一個(gè)空閑隊(duì)列idle

連接池最大活動(dòng)連接數(shù)maxActive

連接池最大等待時(shí)間maxWait

連接池的活動(dòng)連接數(shù)activeSize

程序流程圖如下:

代碼實(shí)現(xiàn)

泛型接口ConnectionPool.java

public interface ConnectionPool {

    /**
     * 初始化池資源
     * @param maxActive 池中最大活動(dòng)連接數(shù)
     * @param maxWait 最大等待時(shí)間
     */
    void init(Integer maxActive, Long maxWait);

    /**
     * 從池中獲取資源
     * @return 連接資源
     */
    T getResource() throws Exception;

    /**
     * 釋放連接
     * @param connection 正在使用的連接
     */
    void release(T connection) throws Exception;

    /**
     * 釋放連接池資源
     */
    void close();


}

以zookeeper為例,實(shí)現(xiàn)zookeeper連接池,ZookeeperConnectionPool.java

public class ZookeeperConnectionPool implements ConnectionPool {
    //最大活動(dòng)連接數(shù)
    private Integer maxActive; 
    //最大等待時(shí)間
    private Long maxWait; 
    //空閑隊(duì)列
    private LinkedBlockingQueue idle = new LinkedBlockingQueue<>();
    //繁忙隊(duì)列
    private LinkedBlockingQueue busy = new LinkedBlockingQueue<>();
    //連接池活動(dòng)連接數(shù)
    private AtomicInteger activeSize = new AtomicInteger(0);
    //連接池關(guān)閉標(biāo)記
    private AtomicBoolean isClosed = new AtomicBoolean(false);
    //總共獲取的連接記數(shù)
    private AtomicInteger createCount = new AtomicInteger(0);
    //等待zookeeper客戶端創(chuàng)建完成的計(jì)數(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();
        
        //空閑隊(duì)列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();
                }
            }
            //若活動(dòng)線程已滿則等待busy隊(duì)列釋放連接
            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("等待異常");
            }
            //判斷是否超時(shí)
            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() + "獲取連接超時(shí),請重試!");
                throw new Exception("Thread:" + Thread.currentThread().getId() + "獲取連接超時(shí),請重試!");
            }
        }
        //空閑隊(duì)列有連接,直接返回
        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個(gè)線程并發(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://systransis.cn/yun/73054.html

相關(guān)文章

  • 阿里 2021 版最全 Java 并發(fā)編程筆記,看完我才懂了“內(nèi)卷”的真正意義

    摘要:純分享直接上干貨操作系統(tǒng)并發(fā)支持進(jìn)程管理內(nèi)存管理文件系統(tǒng)系統(tǒng)進(jìn)程間通信網(wǎng)絡(luò)通信阻塞隊(duì)列數(shù)組有界隊(duì)列鏈表無界隊(duì)列優(yōu)先級有限無界隊(duì)列延時(shí)無界隊(duì)列同步隊(duì)列隊(duì)列內(nèi)存模型線程通信機(jī)制內(nèi)存共享消息傳遞內(nèi)存模型順序一致性指令重排序原則內(nèi)存語義線程 純分享 , 直接上干貨! 操作系統(tǒng)并發(fā)支持 進(jìn)程管理內(nèi)存管...

    不知名網(wǎng)友 評論0 收藏0
  • Java深入-框架技巧

    摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...

    chengtao1633 評論0 收藏0
  • Java多線程編程實(shí)戰(zhàn):模擬大量數(shù)據(jù)同步

    摘要:所以得出結(jié)論需要分配較多的線程進(jìn)行讀數(shù)據(jù),較少的線程進(jìn)行寫數(shù)據(jù)。注意多線程編程對實(shí)際環(huán)境和需求有很大的依賴,需要根據(jù)實(shí)際的需求情況對各個(gè)參數(shù)做調(diào)整。 背景 最近對于 Java 多線程做了一段時(shí)間的學(xué)習(xí),筆者一直認(rèn)為,學(xué)習(xí)東西就是要應(yīng)用到實(shí)際的業(yè)務(wù)需求中的。否則要么無法深入理解,要么硬生生地套用技術(shù)只是達(dá)到炫技的效果。 不過筆者仍舊認(rèn)為自己對于多線程掌握不夠熟練,不敢輕易應(yīng)用到生產(chǎn)代碼中...

    elliott_hu 評論0 收藏0

發(fā)表評論

0條評論

XboxYan

|高級講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<