JUC的数据库连接池小练习

JUC练习数据库连接池实现

  • 通过一个连接数组来充当连接池
  • 一个原子的标记数组
  • 通过cas来保持多线程下的安全,用synchronized来进行暂停和唤醒
@Slf4j
public class MyConnectionPoll {

    // 连接池对象数组
    private Connection[] connections;
    // 使用标记
    private AtomicIntegerArray flagArrays;
    // 线程池大小
    private Integer poolSize;

    public MyConnectionPoll(){
        this.poolSize = 5;
        connections = new MarkConnection[5];
        flagArrays = new AtomicIntegerArray(5);
        for (int i = 0; i < connections.length; i++) {
            connections[i] = new MarkConnection("连接" + i+1);
        }
    }

    // 连接池的初始化
    public MyConnectionPoll(int poolSize) {
        this.poolSize = poolSize;
        connections = new MarkConnection[poolSize];
        flagArrays = new AtomicIntegerArray(poolSize);
        for (int i = 0; i < connections.length; i++) {
            connections[i] = new MarkConnection("连接" + i);
        }
    }

    // 向连接池中请求连接
    public Connection getConnection(){
        while (true){
            for (int i = 0; i < poolSize; i++) {
                // 进行cas请求,如果请求失败就失败
                if (flagArrays.compareAndSet(i,0,1)){
                    return connections[i];
                }
            }
            // 如果请求失败,并且已经没有可用的连接就需要进行等待
            synchronized (this){
                try {
                    // 等待直到被唤醒,然后对所有请求进行遍历找到空闲连接
                    this.wait();  // 调用wait方法需要进行加锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 释放连接
    public void releaseConnection(Connection con){
        for (int i = 0; i < poolSize; i++) {
            if (con == connections[i]){
                flagArrays.set(i,0);  // 将连接标识置为0即空间连接
                synchronized (this){
                    this.notifyAll(); // 唤醒全部等待的线程
                }
            }
        }
    }

    public static void main(String[] args) {
        MyConnectionPoll myConnectionPoll = new MyConnectionPoll(5);
        for (int i = 0; i < 10; i++) {
            new Thread(() ->{
                MarkConnection connection =(MarkConnection) myConnectionPoll.getConnection();
                log.debug("获得锁{}",connection.getConName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myConnectionPoll.releaseConnection(connection);
                log.debug("释放锁{}",connection.getConName());
            }).start();
        }
    }
}
posted @ 2022-05-10 21:22  大队长11  阅读(35)  评论(0编辑  收藏  举报