栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

4种java连接池设计和总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

4种java连接池设计和总结

1.使用HashMap和lock机制
缺点是,在大量的加锁解锁过程中消耗性能
https://blog.csdn.net/shengxiaohua1/article/details/120702347

private Map connectionPool = new HashMap();
private ReentrantLock lock = new ReentrantLock();

public Connection getConnection(String key) {
    try {
        lock.lock();
        if (connectionPool.containsKey(key)) {
            return connectionPool.get(key);
        } else {
            //建立 Connection  
            Connection conn = createConnection();
            connectionPool.put(key, conn);
            return conn;
        }
    } finally {
        lock.unlock();
    }
}

//建立Connection  
private Connection createConnection() {
    return null;
}

上面的代码中HashMap可以替换成ConcurrentHashMap,这样可以不使用lock。但是这样又无法保证创建连接的原子性。产生了下面的方案:

2.使用ConcurrentHashMap和FutureTask作为线程池
ConcurrentHashMap和FutureTask都是线程安全的,故代码里没有额外加锁

    //线程池
    private ConcurrentHashMap connectionPool = new ConcurrentHashMap();

    public Connection getConnection(String key) throws Exception {
        FutureTask connectionTask = connectionPool.get(key);
        if (connectionTask != null) {
            return connectionTask.get();
        } else {
            Callable callable = new Callable() {
                @Override
                public Connection call() throws Exception {
                    // TODO Auto-generated method stub  
                    return createConnection();
                }
            };
            FutureTask newTask = new FutureTask(callable);
            //map中没有key就put,存在key就返回null
            connectionTask = connectionPool.putIfAbsent(key, newTask);
            if (connectionTask == null) {
                connectionTask = newTask;
                //FutureTask内部使用适配器模式,在run方法中调用了call方法
                connectionTask.run();
            }
            //get等待run方法执行完返回结果
            return connectionTask.get();
        }
    }

    //建立Connection  
    private Connection createConnection() {
        return null;
    }

3.LinkedList + Semaphore

public class DBPoolSemaphore {

    
    private final static int POOL_SIZE = 10;

    
    private final Semaphore useful, useless;

    
    private final static LinkedList POOL = new LinkedList<>();

    
    static {
        for (int i = 0; i < POOL_SIZE; i++) {
            POOL.addLast(SqlConnection.fetchConnection());
        }
    }

    public DBPoolSemaphore() {
        // 初始可用的许可证等于池容量
        useful = new Semaphore(POOL_SIZE);
        // 初始不可用的许可证容量为0
        useless = new Semaphore(0);
    }

    
    public Connection takeConnection() throws InterruptedException {
        // 可用许可证减一
        useful.acquire();
        Connection connection;
        synchronized (POOL) {
            connection = POOL.removeFirst();
        }
        // 不可用许可证数量加一
        useless.release();
        return connection;
    }

    
    public void returnConnection(Connection connection) throws InterruptedException {
        if(null!=connection){
            // 打印日志
            System.out.println("当前有"+useful.getQueueLength()+"个线程等待获取连接,,"
                    +"可用连接有"+useful.availablePermits()+"个");
            // 不可用许可证减一
            useless.acquire();
            synchronized (POOL){
                POOL.addLast(connection);
            }
            // 可用许可证加一
            useful.release();
        }
    }
}

4.java并发编程艺术208页
LinkedList + synchronized + Object.wait/Object.notify

public class ConnectionPool {
    private LinkedList pool = new LinkedList();
    public ConnectionPool(int initialSize) {
        if (initialSize > 0) {
            for (int i = 0; i < initialSize; i++) {
                pool.addLast(ConnectionDriver.createConnection());
            }
        }
    }
    public void releaseConnection(Connection connection) {
        if (connection != null) {
            synchronized (pool) {
// 连接释放后需要进行通知,这样其他消费者能够感知到连接池中已经归还了一个连接
                pool.addLast(connection);
                pool.notifyAll();
            }
        }
    }
    // 在mills内无法获取到连接,将会返回null
    public Connection fetchConnection(long mills) throws InterruptedException {
        synchronized (pool) {
// 完全超时
            if (mills <= 0) {
                while (pool.isEmpty()) {
                    pool.wait();
                }
                return pool.removeFirst();
            } else {
                long future = System.currentTimeMillis() + mills;
                long remaining = mills;
                while (pool.isEmpty() && remaining > 0) {
                    pool.wait(remaining);
                    remaining = future - System.currentTimeMillis();
                }
                Connection result = null;
                if (!pool.isEmpty()) {
                    result = pool.removeFirst();
                }
                return result;
            }
        }
    }
}

总结
1、线程池需要一个保存所有线程的容器,可以选择HashMap,可以选择LinkedList等。
2、获取线程的时候由于存在竞争,所以需要枷锁lock或synchronized。
3、还需要监控池子中的容量,使用semaphore计数阻塞或Object.wait或LockSupport.park,总之当容量没有剩余的时候需要阻塞。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/872299.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号