文档章节

简易数据库连接池

meshwon
 meshwon
发布于 2017/09/13 16:30
字数 876
阅读 7
收藏 0

1、连接池初始化:

public class ConnectionPool {
    private LinkedList<Connection> pool = new LinkedList<Connection>();

    // 初始化连接池
    public ConnectionPool(int size) {
        if (size > 0) {
            for (int i = 0; i < size; i++) {
                pool.addLast(ConnectionDriver.createConnection());
            }
        }
    }

    // 释放一个连接
    public void realseConnection(Connection conn) {
        synchronized (pool) {
            pool.addLast(conn);// 用完的连接返回连接池
            pool.notifyAll();// 连接池有新的数据通知所有等待的线程来获取新的连接
        }
    }

    // 从连接池中获取一个连接
    public Connection getConnection(int mills) throws InterruptedException {// 超时自动返回
        synchronized (pool) {
            if (mills <= 0) {
                while (pool.size() <= 0) {
                    pool.wait();// 等待,直到获取到一个连接返回
                }
                return pool.removeFirst();
            }
            long curentMills = System.currentTimeMillis() + mills;
            long remaining = mills;
            while (pool.size() <= 0 && remaining > 0) {
                pool.wait(remaining);// 超时直接返回null
                remaining = curentMills - System.currentTimeMillis();// 连接数不足,并且超时未到,继续等待
            }
            if (pool.size() > 0) {
                return pool.removeFirst();
            }
            return null;
        }
    }
}

2.模拟一个数据库驱动:

public class ConnectionDriver {
    static class ConnectionHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("commit")) {
                TimeUnit.MILLISECONDS.sleep(100);
            }
            return null;
        }

    }

    public static final Connection createConnection() {
        return (Connection) Proxy.newProxyInstance(ConnectionHandler.class.getClassLoader(),
                new Class<?>[] { Connection.class }, new ConnectionHandler());
    }
}

3.该连接池的使用方法,使用到了可以进行原子操作的AtomicInteger以及CountDownLatch工具类。

    CountDownLatch介绍:

         CountDownLatch 多个线程同时工作,然后其中几个可以随意并发执行, 但有一个线程需要等其他线程 ,工作结束后,才能开始。举个例子,开启多个线程分块下载一个大文件, 每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段, 那么这时候我们可以考虑使用CountDownLatch来控制并发。
       CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。

public class ConnectionPoolTest {

    public static ConnectionPool pool = new ConnectionPool(10);// 初始化线程池
    public static CountDownLatch start = new CountDownLatch(1); // 所有线程同时执行任务
    public static CountDownLatch end; // 子线程执行完成后主线程执行的标志

    public static void main(String[] args) throws InterruptedException {
        int count = 40;
        int threadCount = 40;
        end = new CountDownLatch(threadCount);
        AtomicInteger got = new AtomicInteger();// 可以进行原子操作的Integer
        AtomicInteger notGot = new AtomicInteger();
        for (int i = 0; i < threadCount; i++) {
            new Thread(new ConnectionRunner(count, got, notGot), "pool").start();
        }
        start.countDown(); // 计数器减1,计算器==0则阻塞完成
        end.await();// 主线程等待所有子线程执行完成
        System.out.println("total invoke : " + (threadCount * count));
        System.out.println("got connection : " + got);
        System.out.println("not got connection : " + notGot);
    }

    static class ConnectionRunner implements Runnable {
        private int count;
        private AtomicInteger got;
        private AtomicInteger notGot;

        /**
         * @param count
         * @param got
         * @param notGot
         */
        public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot) {
            this.count = count;
            this.got = got;
            this.notGot = notGot;
        }

        @Override
        public void run() {
            try {
                start.await(); // 子线程等待,直到所有子线程创建完成
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            while (count > 0) {
                try {
                    Connection conn = pool.getConnection(3000);
                    if (conn != null) {
                        try {
                            conn.createStatement();
                            conn.commit();
                        }
                        finally {
                            pool.realseConnection(conn);
                            got.incrementAndGet();// 原子加1操作
                        }

                    }
                    else {
                        notGot.incrementAndGet();
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                finally {
                    count--;
                }
            }
            end.countDown();
        }

    }
}

 

© 著作权归作者所有

共有 人打赏支持
上一篇: springmvc实例
下一篇: java日期操作
meshwon
粉丝 1
博文 29
码字总数 19085
作品 0
哈尔滨
程序员
私信 提问
线程中数据库连接导致内存泄露

各位大神好,小弟初入Java,以上代码是自己写的一个简易数据库连接类,代码笨拙,提出以下疑问: 1,在1处,如果是return con,会不会造成内存泄露或者不可预见 的错误 2,在2处,我原先是写...

keweih
2015/08/10
275
0
common-tools

java工具类,提供常用的功能方法,例如:时间工具、数据库连接池工具、ssh端口映射(已与数据库连接集成)、支持变量替换和自定义字符集的配置文件类、多线程工具类、文件读写工具类等等。还...

路小磊
2013/02/22
3.6K
0
数据库简易帮助包

源码在:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/jdbc?dir=1&filepath=ajaxjs-base%2Fsrc%2Fcom%2Fajaxjs%2Fjdbc 概述 从 JDBC 规范上看,其对数据访问......

zhangxin09
2017/02/19
0
0
C语言网络框架库--acl

acl 框架库是一个 C 库,主要包含:服务器开发框架、同步/异步网络通讯、常用数据结构、进程池/线程池、流式 xml/json 解析器、http/ping 应用协议等内容; acl 包括以下丰富的常用函数库: ...

郑树新
2012/06/03
21.4K
3
Java爬虫抓取知乎20万用户信息并做简易分析

前段时间看@路人甲 分享了一篇爬取知乎用户的文章,心血来潮,想着也该把自己很早写的知乎爬虫完善一下 趁着每天实习回来还有点时间,整理了下思路和原来的代码 因为自己不太爱用框架,所以爬...

KKys
2017/01/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【机器学习PAI实战】—— 玩转人工智能之商品价格预测

摘要: 我们经常思考机器学习,深度学习,以至于人工智能给我们带来什么?在数据相对充足,足够真实的情况下,好的学习模型可以发现事件本身的内在规则,内在联系。我们去除冗余的信息,可以...

zhaowei121
9分钟前
0
0
Spring拓展接口之FactoryBean,我们来看看其源码实现

是什么 FactoryBean的源码比较简单,大家可以细读下其注释,我做了简单的如下翻译 /** * 实现此接口的bean不能用作普通bean。此bean暴露的对象是通过getObject()创建的对象,而不是它自身...

java菜分享
13分钟前
1
0
Pod在多可用区worker节点上的高可用部署

一、 需求分析 当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用...

阿里云官方博客
19分钟前
0
0
深入理解 Hive 分区分桶 (Inceptor)

分区是hive存放数据的一种方式。将列值作为目录来存放数据,就是一个分区。这样查询时使用分区列进行过滤,只需根据列值直接扫描对应目录下的数据,不扫描其他不关心的分区,快速定位,提高查...

hblt-j
27分钟前
0
0
数据结构

什么是数据结构 1、数据 数据是描述客观世界的数字、字符以及一切能够输入到计算机中,并且能够被计算机程序处理的符号集合。简言之,数据就是计算机加工处理的原料,是信息的载体。 2、数据...

stars永恒
37分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部