자바 동기 화 입도 축소 실천

6915 단어 synchronized
프로젝트 요구 사항:
제품 은 다양한 종류의 데이터 베 이 스 를 감시 해 야 합 니 다.예 를 들 어 여러 my sql 라 이브 러 리,여러 Oacle 라 이브 러 리,여러 sybase 라 이브 러 리,여러 msserver 라 이브 러 리 등 연결 탱크 는 고객 데이터 베이스 종류 와 수량의 실제 상황 에 따라 동적 으로 만들어 야 합 니 다.
 
난점:
1.라 이브 러 리 마다 연결 풀 을 만 들 고 반복 해서 만 들 수 없습니다.
2.모든 연결 탱크 는 자신의 스 레 드 안전성 을 유지 하고 모든 연결 탱크 의 스 레 드 를 방문 하여 단독으로 줄 을 서 며 서로 영향 을 주지 않 습 니 다.
 
실현 방향:
모든 라 이브 러 리 의 연결 탱크 인 스 턴 스 를 static Map 에 저장 합 니 다.key 는 라 이브 러 리 경로 이 고 value 는 연결 탱크 대상 입 니 다.대상 이 존재 하면 만 들 지 않 고 가 져 옵 니 다.
 
Map 의 read-write 조합 작업 은 라인 안전 제어 가 필요 합 니 다.연결 풀 대상 을 만 들 때 pool 대상 을 초기 화 해 야 합 니 다.이것 은 시간 이 걸 리 는 작업 입 니 다.이 때 문 제 를 설명 합 니 다.무엇 을 잠 금 으로 맵 에 대한 조작 을 잘 제어 합 니까?
 
만약 에 전체 변수 가 잠 겨 있 으 면 서로 다른 데이터 베 이 스 를 여기 서 막 을 수 있 습 니 다.만약 에 데이터 베 이 스 를 지연 시 키 면 다른 데이터 베이스 도 대량으로 막 힐 것 입 니 다.라 이브 러 리 주 소 를 독점 자물쇠 로 사용 하면 서로 다른 데이터 베 이 스 를 각각 줄 을 서 게 되 고 라 이브 러 리 와 라 이브 러 리 사이 에는 영향 이 없다.라 이브 러 리 경로 가 String 대상 이기 때문에 자바 String 대상 이 잠 금 변 수 를 만 들 수 있 는 지 시험 해 봤 습 니 다.결론 은 자바 String 대상 이 Synchronized()의 잠 금 변수 로 사용 할 수 없다 는 것 이다.하지만 오 브 젝 트 대상 은 자물쇠 로 쓸 수 있어 요.이상해 요!
 
전역 변수 에 자 물 쇠 를 추가 할 수 없 는 주요 원인 은 연결 탱크 의 대상 을 초기 화 하 는 시간 이 비교적 길 고 라인 줄 이 비교적 심각 하 며 다 중 데이터베이스 간 에 서로 영향 을 미 치기 때문이다.따라서 데이터베이스 경 로 를 key 로 하고 Object 대상 을 value 로 하 는 잠 금 집합 을 추가 하 는 것 을 고려 합 니 다.그러면 Object 대상 을 빨리 가 져 올 수 있 고 이 대상 을 key(데이터베이스 경로)대신 synchrozied 의 잠 금 변수 로 사용 할 수 있 습 니 다.상위 코드:
 
 
import java.sql.Connection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.mchange.v2.c3p0.ComboPooledDataSource;


public class XJDBCPool {
    public static enum DBTYPE {
        Oracle, Sybase, Mysql, Mssql, DB2, Informix
    };
    
    //locks map
    public final static Map<String, Object> locks = new ConcurrentHashMap<String, Object>();
    //pool map
    public final static Map<String, C3p0Pool> jdbcPoolC3p0s = new ConcurrentHashMap<String, C3p0Pool>();
    
    
    private static XConnection getXCon(String key, String type) {
        Logger.logDebug("~~~~ XJDBCPool getXCon key : "+ key);
        
        int timeoutIndex = key.lastIndexOf("#");
        String timeStr = key.substring(timeoutIndex + 1) == null ? "" : key.substring(timeoutIndex + 1);
        int timeout = Integer.valueOf(timeStr);
        key = key.substring(0, timeoutIndex);
        
        C3p0Pool c3p0Pool = null;
        if(type.equals(JDBC_TYPE_C3P0)){
            
            Object obj = null;
            synchronized(locks){
                obj = locks.get(key);
                if(obj == null){
                    obj = new Object();
                    locks.put(key, obj);
                }
            }
            
            Logger.logDebug("~~~~ ["+ Thread.currentThread().getName() +"] wait lock : "+ obj +" key : "+ key);
            synchronized(obj){
            Logger.logDebug("~~~~ ["+ Thread.currentThread().getName() +"] get lock : "+ obj +" key : "+ key);
                
                c3p0Pool = jdbcPoolC3p0s.get(key);
                if (c3p0Pool == null){
		    //init pool
                    c3p0Pool = new C3p0Pool(key, timeout);
                    jdbcPoolC3p0s.put(key, c3p0Pool);
                    
                } else{
                    //if timeout was modified, restart pool.
                    int timeoutOld = 0;
                    ComboPooledDataSource cpds = c3p0Pool.getCpds();
                    if(cpds != null){
                        timeoutOld = cpds.getCheckoutTimeout();
                        if(timeout * 1000 != timeoutOld){
                            c3p0Pool.release();
                            cpds = c3p0Pool.init(key, timeout);
                            jdbcPoolC3p0s.put(key, c3p0Pool);
                        }
                    }
                }
            }
            Logger.logDebug("~~~~ ["+ Thread.currentThread().getName() +"] release lock : "+ obj +" key : "+ key);
            
        }
        
        return c3p0Pool.getConnection();
    }
    
    ....

}

 
 
"String 대상 은 synchrozied 의 잠 금 변수 로 사용 할 수 없습니다."
테스트 프로그램 은 다음 과 같 습 니 다.콘 솔 출력 은 모두 가 알 아 볼 수 있다 고 믿 고 더 이상 설명 하지 않 습 니 다.
 
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;


public class TestSynchronizedStr {
	public static Logger logger = Logger.getLogger(LoggerManager.PLATFORM);
	public final static Map<String, Object> locks = new ConcurrentHashMap<String, Object>();
	private final static Map<String, Object> jdbcPoolC3p0s = new ConcurrentHashMap<String, Object>();
		
	/**
	 * test ConcurrentHashMap
	 */
	public static void testConcurrentMap(String key){
		Object obj = null;
        synchronized(locks){
            obj = locks.get(key);
            if(obj == null){
                obj = new Object();
                locks.put(key, obj);
            }
        }
		
		logger.debug("~~~~ ["+ Thread.currentThread().getName() +"] wait lock : "+ key);
		synchronized(obj){
			logger.debug("~~~~ ["+ Thread.currentThread().getName() +"] get lock : "+ key);			
		
	        try{
				Thread.sleep(10000L);
			} catch(Exception e){
				e.printStackTrace();
			}
	        logger.debug("~~~~ ["+ Thread.currentThread().getName() +"] release lock : "+ key);
		}
	}
	
	
	public static void startThreads(final String i) {		
		Thread[] threads = new Thread[10];
		
		for(int j = 0; j < threads.length; j++){
			threads[j] = new Thread(){
				public void run(){
					logger.debug("

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); logger.debug("**** start ["+ Thread.currentThread().getName() +"]"); testConcurrentMap(i); } }; threads[j].start(); } } public static void main(String[] args) { for (int i = 0; i < 50; i++) { Random random = new Random(); int randNum = Math.abs(random.nextInt())%3; startThreads(randNum +""); } } }

 
 

좋은 웹페이지 즐겨찾기