Java ConcurrentMap 마스터: 스레드 안전한 맵 연산 완벽 이해
Java ConcurrentMap 인터페이스
Java의 ConcurrentMap이 어떻게 스레드 안전 맵 연산을 제공하는지, 핵심 메서드와 ConcurrentHashMap 실전 예제로 학습합니다.
ConcurrentMap 인터페이스는 java.util.Map을 확장하며 맵의 고도로 동시적이고 스레드 안전한 구현을 제공합니다. 여러 스레드가 맵의 내부 상태를 손상시키지 않고 동시에 읽기, 쓰기, 업데이트 연산을 수행할 수 있음을 보장합니다.
ConcurrentMap은 인터페이스이므로 직접 인스턴스화할 수 없습니다. 가장 일반적인 구현체는 java.util.concurrent.ConcurrentHashMap으로, 락 프리 읽기와 업데이트를 위한 세분화된 락을 제공합니다.
ConcurrentMap을 구현하는 클래스들
ConcurrentMap 자체는 인스턴스화할 수 없지만, 구현체 중 하나로 구체 맵을 생성할 수 있습니다. 사실상 표준은 ConcurrentHashMap이지만, 정렬 맵 요구사항에는 ConcurrentSkipListMap 같은 대안도 존재합니다.
ConcurrentMap 사용하기
먼저 인터페이스를 임포트하세요:
import java.util.concurrent.ConcurrentMap;
ConcurrentHashMap 인스턴스 생성:
ConcurrentMap<String, Integer> numbers = new ConcurrentHashMap<>();
이 예제에서 numbers는 각 String 키가 Integer 값과 쌍을 이루는 스레드 안전 맵입니다.
핵심 개념:
- Key – 값에 매핑되는 고유 식별자
- Value – 키와 연관된 데이터
ConcurrentMap 핵심 메서드
모든 표준 Map 연산 외에 ConcurrentMap은 여러 원자적, 락 프리 메서드를 도입합니다:
- putIfAbsent(K key, V value) – 키가 없을 때만 키/값 쌍 추가
- compute(K key, BiFunction) – 현재 값을 기반으로 지정된 키의 값을 원자적으로 업데이트
- computeIfAbsent(K key, Function) – 제공된 함수로 누락된 키의 값 생성
- computeIfPresent(K key, BiFunction) – 기존 키의 값을 원자적으로 업데이트
- forEach(BiConsumer) – 각 엔트리에 주어진 액션 수행
- merge(K key, V value, BiFunction) – 제공된 함수로 새 값을 기존 값과 결합
심층 참조는 공식 Java 문서를 참조하세요.
ConcurrentHashMap과 ConcurrentMap 사용 예제
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
public class Main {
public static void main(String[] args) {
// 스레드 안전 맵 생성
ConcurrentMap<String, Integer> numbers = new ConcurrentHashMap<>();
// 요소 삽입
numbers.put("Two", 2);
numbers.put("One", 1);
numbers.put("Three", 3);
System.out.println("ConcurrentMap: " + numbers);
// 값 검색
int value = numbers.get("One");
System.out.println("Accessed Value: " + value);
// 키/값 쌍 제거
int removed = numbers.remove("Two");
System.out.println("Removed Value: " + removed);
}
}
출력
ConcurrentMap: {One=1, Two=2, Three=3} Accessed Value: 1 Removed Value: 2
고급 사용법은 ConcurrentHashMap 문서를 참조하세요.