多线程占用临界资源

Updated on in 程序人生 with 0 views and 0 comments

临界资源需要保持他的唯一性,再代码中,可以通过单例模式来实现(这里是典型的生产者/消费者问题)

构造方法中,用synchronized来做同步处理,为了避免每次进来都要给代码加锁影响性能,先在外层套if做判断

这里的connectionMap就是一个临界资源,代码初始化创建了8个数据库链接,放在map里面,然后多线程来获取调用这些connection

为了保证临界资源的安全,对获取链接和放回链接做了一个枷锁的处理,建立一个ReentrantLock锁,然后获取两个条件,获取连接的时候,判断是否有链接,有就继续,放回链接的时候,判断链接池是否已经满了,没满就放回

package cn.com.enersun.datahub.powerevent.consumer.database;

import java.sql.Connection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * Postgres执行器
 * @author Mr.Wen
 */
public class Postgresql extends DatabaseCommonOperator  implements Database{
    private static final int CONNECTION_POOL_SIZE = 8;
    private static Map<String,LinkedList<Connection>> connectionMap = new HashMap<>();
    private static volatile Postgresql postgresql = null;
    private Lock lock;
    private Condition consumer;
    private Condition producer;
    private Postgresql(){
        lock = new ReentrantLock();
        consumer = lock.newCondition();
        producer = lock.newCondition();
    }

    /**
     * 初始化对象,创建链接池
     * @param driveClassName 数据库驱动名称
     * @param url 数据库连接
     * @param username 数据库用户名
     * @param password 数据库密码
     * @return 返回对象
     */
    public static Postgresql getInstance(String driveClassName,String url, String username, String password){
        //第一次加载
        if(null == postgresql){
            synchronized (Postgresql.class){
                if(null == postgresql){
                    postgresql = new Postgresql();
                    LinkedList<Connection> connectionsList = new LinkedList<>();
                    for(int i=0;i<CONNECTION_POOL_SIZE;i++){
                        connectionsList.add(createConnection(driveClassName,url,username,password));
                    }
                    connectionMap.put(url,connectionsList);
                }
            }
        }else{
            synchronized (Postgresql.class){
                if(!connectionMap.containsKey(url)){
                    LinkedList<Connection> connectionsList = new LinkedList<>();
                    for(int i=0;i<CONNECTION_POOL_SIZE;i++){
                        connectionsList.add(createConnection(driveClassName,url,username,password));
                    }
                    connectionMap.put(url,connectionsList);
                }
            }
        }
        return postgresql;
    }

    public Connection getConnection(String url) {
        lock.lock();
        try{
            LinkedList<Connection> connections = connectionMap.get(url);
            while (connections.size() == 0){
                consumer.wait();
            }
            Connection connection = connections.remove(0);
            producer.signal();
            return connection;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return null;
    }

    public void returnConnection(Connection connection,String url){
        lock.lock();
        try {
            LinkedList<Connection> connections = connectionMap.get(url);
            while (connections.size() == CONNECTION_POOL_SIZE){
                producer.wait();
            }
            consumer.signal();
            connections.add(connection);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

标题:多线程占用临界资源
作者:wenyl
地址:http://www.wenyoulong.com/articles/2020/07/31/1596183328668.html