자바 의 Copy-On-Write 용기
CopyonWrite 용기 가 뭐 예요?
CopyOnWrite 용 기 는 쓰기 전에 복사 한 용기 입 니 다.일반적인 이 해 는 우리 가 한 용기 에 요 소 를 추가 할 때 현재 용기 에 직접 추가 하지 않 고 현재 용 기 를 복사 하여 새로운 용 기 를 복사 한 다음 에 새로운 용기 에 요 소 를 추가 하고 요 소 를 추가 한 다음 에 원래 용기 의 인용 을 새로운 용기 에 가리 키 는 것 이다.이렇게 하 는 장점 은 현재 용기 에 어떠한 요소 도 추가 하지 않 기 때문에 CopyOnWrite 용 기 를 동시에 읽 을 수 있다 는 것 이다.그래서 CopyonWrite 용기 도 읽 기와 쓰기 가 분 리 된 사상 으로 읽 기와 쓰기 가 다른 용기 입 니 다.
CopyOnWriteArrayList 의 실현 원리
CopyOn WriteArray List 를 사용 하기 전에 우 리 는 먼저 그 소스 코드 를 읽 고 그것 이 어떻게 실현 되 었 는 지 알 아 보 자.다음 코드 는 ArrayList 에 요 소 를 추가 합 니 다.추가 할 때 자 물 쇠 를 추가 해 야 합 니 다.그렇지 않 으 면 다 중 스 레 드 를 쓸 때 N 개의 복사 본 을 복사 합 니 다.
public boolean add(T e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//
Object[] newElements = Arrays.copyOf(elements, len + 1);
//
newElements[len] = e;
//
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
final void setArray(Object[] a) {
array = a;
}
읽 을 때 자 물 쇠 를 추가 할 필요 가 없습니다.읽 을 때 여러 스 레 드 가 Array List 에 데 이 터 를 추가 하고 있 으 면 읽 을 때 오래된 데 이 터 를 읽 습 니 다.쓸 때 오래된 Array List 를 잠 그 지 않 기 때 문 입 니 다.
public E get(int index) {
return get(getArray(), index);
}
JDK 에서 CopyOnWriteMap 을 제공 하지 않 았 습 니 다.CopyOnWriteArray List 를 참고 하여 하 나 를 실현 할 수 있 습 니 다.기본 코드 는 다음 과 같 습 니 다.
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
private volatile Map<K, V> internalMap;
public CopyOnWriteMap() {
internalMap = new HashMap<K, V>();
}
public V put(K key, V value) {
synchronized (this) {
Map<K, V> newMap = new HashMap<K, V>(internalMap);
V val = newMap.put(key, value);
internalMap = newMap;
return val;
}
}
public V get(Object key) {
return internalMap.get(key);
}
public void putAll(Map<? extends K, ? extends V> newData) {
synchronized (this) {
Map<K, V> newMap = new HashMap<K, V>(internalMap);
newMap.putAll(newData);
internalMap = newMap;
}
}
}
실현 은 매우 간단 하 다.CopyOnWrite 체 제 를 이해 하면 우 리 는 각종 CopyOnWrite 용 기 를 실현 하고 서로 다른 응용 장면 에서 사용 할 수 있다.
CopyonWrite 의 응용 장면
CopyonWrite 병발 용 기 는 다 중 쓰기 가 적은 병발 장면 을 읽 는 데 사용 된다.예 를 들 어 화이트 리스트,블랙리스트,상품 류 의 방문 과 업데이트 장면,만약 에 우리 가 검색 사이트 가 있다 면 사용 자 는 이 사이트 의 검색 상자 에 키워드 검색 내용 을 입력 하지만 일부 키 워드 는 검색 되 지 않 습 니 다.검색 할 수 없 는 키 워드 는 블랙리스트 에 올 라 가 매일 저녁 한 번 씩 블랙리스트 가 업데이트 된다.사용자 가 검색 할 때 현재 키워드 가 블랙리스트 에 없 는 지 확인 합 니 다.있 으 면 검색 할 수 없 음 을 알려 줍 니 다.구현 코드 는 다음 과 같 습 니 다:
package com.ifeve.book;
import java.util.Map;
import com.ifeve.book.forkjoin.CopyOnWriteMap;
/**
*
*
* @author fangtengfei
*
*/
public class BlackListServiceImpl {
private static CopyOnWriteMap<String, Boolean> blackListMap = new CopyOnWriteMap<String, Boolean>(
1000);
public static boolean isBlackList(String id) {
return blackListMap.get(id) == null ? false : true;
}
public static void addBlackList(String id) {
blackListMap.put(id, Boolean.TRUE);
}
/**
*
*
* @param ids
*/
public static void addBlackList(Map<String,Boolean> ids) {
blackListMap.putAll(ids);
}
}
코드 는 간단 하지만 CopyOnWriteMap 을 사용 하려 면 두 가지 일 을 주의해 야 합 니 다.
1.확장 비용 을 줄인다.실제 수요 에 따라 CopyOnWriteMap 의 크기 를 초기 화하 여 쓸 때 CopyOnWriteMap 의 확장 비용 을 피 합 니 다.
2.대량 추가 사용.매번 추가 할 때마다 용기 가 매번 복사 되 기 때문에 추가 횟수 를 줄 이면 용기 의 복사 횟수 를 줄 일 수 있다.위 코드 에 있 는 addBlackList 방법 을 사용 하면
CopyonWrite 의 단점
CopyonWrite 용 기 는 장점 이 많 지만 메모리 점용 문제 와 데이터 일치 성 문제 도 두 가지 문제 가 존재 합 니 다.그래서 개발 할 때 주의 가 필요 합 니 다.
메모리 사용량 문제.CopyOnWrite 의 쓰기 시 복사 메커니즘 때문에 쓰기 작업 을 할 때 메모리 에 두 대상 의 메모리,오래된 대상 과 새로 쓴 대상 이 동시에 주둔 합 니 다.(주의:복사 할 때 용기 의 인용 만 복사 하고 쓸 때 새 대상 을 만들어 새 용기 에 추가 합 니 다.오래된 용기 의 대상 은 사용 하고 있 습 니 다.그래서 두 개의 대상 메모리 가 있 습 니 다.만약 에 이 대상 들 이 차지 하 는 메모리 가 비교적 크다 면,예 를 들 어 200 M 정도 이다.그러면 100 M 데 이 터 를 다시 써 넣 으 면 메모리 가 300 M 을 차지한다.그러면 이 럴 때 빈번 한 Yong GC 와 Full GC 를 초래 할 수 있다.이전에 저희 시스템 에서 하나의 서 비 스 를 사 용 했 습 니 다.매일 밤 CopyOn Write 체 제 를 사용 하여 큰 대상 을 업데이트 하기 때문에 매일 밤 15 초의 Full GC 를 만 들 었 고 응용 응답 시간 도 길 어 졌 습 니 다.
메모리 점용 문제 에 대해 서 는 용기 에 있 는 요 소 를 압축 하 는 방법 으로 대상 의 메모리 소 모 를 줄 일 수 있 습 니 다.예 를 들 어 요소 가 모두 10 진법 의 숫자 라면 36 진법 이나 64 진법 으로 압축 하 는 것 을 고려 할 수 있 습 니 다.또는 CopyOnWrite 용 기 를 사용 하지 않 고 다른 병발 용 기 를 사용 합 니 다.예 를 들 어 ConcurrentHashMap.
데이터 일치 성 문제.CopyonWrite 용 기 는 데이터 의 최종 일치 성 만 보장 할 수 있 을 뿐 데이터 의 실시 간 일치 성 을 보장 할 수 없습니다.따라서 원 하 는 데 이 터 를 읽 을 수 있 습 니 다.CopyOnWrite 용 기 를 사용 하지 마 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.