자바 동기 화 입도 축소 실천
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 +"");
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
javasynchronized 동기화 정적 방법과 동기화 비정적 방법의 공통점우리는synchronized를 사용하여 대상 변수를 동기화할 수 있을 뿐만 아니라,synchronizedl를 통해 동기화 클래스의 정적 방법과 비정적 방법을 동기화할 수 있습니다. 자바 관련 문법에서 알 수 있듯이s...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.