连接池小实例

工作之余看了一下Java的等待通知机制原理,然后里面有一个数据库连接池的小Demo,觉得蛮有意思。所以看完之后,自己动手写了一个简单的实例,代码虽然简单,但是对于理解连接池还是小有帮助。话不多说,直接上代码。
链接占位:后面有时间了再来总结Java的等待通知机制


连接定义

public class Connection {

    public void execute() {
        try {
            Thread.sleep((long) (Math.random() * 10));
        } catch (InterruptedException e) {
        }
    }
}

连接驱动定义

public class ConnectionDriver {

    public static Connection createConnection() {
        return new Connection();
    }
}

连接池定义

public class ConnectionPool {

    private final LinkedList<Connection> pool = new LinkedList<>();

    public ConnectionPool(int count) {
        if (count <= 0) {
            count = 1;
        }
        for (int i = 0;i < count;i++) {
            pool.addLast(ConnectionDriver.createConnection());
        }
    }

    public Connection fetchConnection() throws InterruptedException {
        return fetchConnection(-1);
    }

    public Connection fetchConnection(int mil) throws InterruptedException {
        synchronized (pool) {
            if (mil <= 0) {
                while (pool.isEmpty()) {
                    pool.wait();
                }
                return pool.removeFirst();
            } else {
                long fuTime = System.currentTimeMillis() + mil;
                long remain = mil;
                while (pool.isEmpty() && remain > 0) {
                    pool.wait(remain);
                    remain = fuTime - System.currentTimeMillis();
                }
                Connection result = null;
                if (!pool.isEmpty()) {
                    result = pool.removeFirst();
                }
                return result;
            }
        }
    }

    public void releaseConnection(Connection connection) {
        if (connection == null) {
            return;
        }
        synchronized (pool) {
            pool.addLast(connection);
            pool.notifyAll();
        }
    }
}

连接池测试

public class ConnectionPollCeshi {

    public static void main(String[] args) throws InterruptedException {
        int threadCount = 10;
        ConnectionPool pool = new ConnectionPool(5);

        CyclicBarrier start = new CyclicBarrier(1);
        CountDownLatch end = new CountDownLatch(threadCount);
        AtomicInteger gotSuccess = new AtomicInteger();
        AtomicInteger gotFailed = new AtomicInteger();

        for (int i = 0;i < threadCount;i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        start.await();
                    } catch (Exception e) { }

                    for (int i = 0;i < 10;i++) {
                        try {
                            Connection connection = pool.fetchConnection(2);
                            if (connection == null) {
                                gotFailed.incrementAndGet();
                            } else {
                                connection.execute();
                                pool.releaseConnection(connection);
                                gotSuccess.incrementAndGet();
                            }
                        } catch (InterruptedException e) {
                            gotFailed.incrementAndGet();
                        }
                    }

                    end.countDown();
                }
            }).start();
        }

        end.await();
        System.out.println("获取成功: " + gotSuccess.get());
        System.out.println("获取失败: " + gotFailed.get());
    }
}

运行结果

获取成功: 48
获取失败: 5

实现原理

上面使用了经典的等待通知机制,分为等待角色和通知角色,如下:

等待角色伪代码

{
  while(条件不变) {
    obj.wait();
  }
}

通知角色伪代码

{
  改变条件
  obj.notifyAll();
}

对于Java等待通知里面的等待队列、同步队列还有很多值得梳理的地方,后面有时间后来认真总结,今天划水就先划到这里。

posted @ 2021-05-19 15:24  小白先生哦  阅读(126)  评论(0编辑  收藏  举报