简易数据库连接池

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();
        }

    }
}

 

转载于:https://my.oschina.net/meshwon/blog/1536842

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值