해시맵 대 ConcurrentHashMap 대. SynchronizedMap – Java에서 HashMap을 동기화하는 방법

게시 됨: 2015-01-29

ConcurrentHashMap 대 Crunchify SynchronizedMap 예제 HashMap 은 Java에서 매우 강력한 데이터 구조입니다. 우리는 매일 거의 모든 응용 프로그램에서 사용합니다. Threadsafe 캐시를 구현하는 방법, Hashmap을 Arraylist로 변환하는 방법에 대해 이전에 작성한 몇 가지 예가 있습니다.

위의 두 예제에서 Hashmap을 사용했지만 Hashmap의 아주 간단한 사용 사례입니다. HashMap is a non-synchronized 컬렉션 클래스입니다.

아래 질문이 있습니까?

  • ConcurrentHashMap과 Collections.synchronizedMap(Map)의 차이점은 무엇입니까?
  • 성능 면에서 ConcurrentHashMap과 Collections.synchronizedMap(Map)의 차이점은 무엇입니까?
  • ConcurrentHashMap 대 Collections.synchronizedMap()
  • 인기있는 HashMap 및 ConcurrentHashMap 인터뷰 질문

이 튜토리얼에서는 위의 모든 쿼리와 해시맵을 동기화할 수 있는 why and how 을 살펴보겠습니다.

왜요?

Map 객체는 고유하게 식별되는 key 와 매핑된 value 의 조합으로 형성된 요소를 저장하는 연관 컨테이너입니다. 다른 스레드에서 키 값을 수정하거나 읽으려는 매우 동시성이 높은 애플리케이션이 있는 경우 Concurrent Hashmap을 사용하는 것이 이상적입니다. 가장 좋은 예는 동시 읽기/쓰기를 처리하는 생산자 소비자입니다.

그렇다면 스레드로부터 안전한 맵은 무엇을 의미합니까? multiple threads 가 해시 맵에 동시에 액세스하고 스레드 중 적어도 하나가 구조적으로 맵을 수정하는 경우 콘텐츠의 일관성 없는 보기를 피하기 위해 must be synchronized externally .

어떻게?

HashMap을 동기화할 수 있는 두 가지 방법이 있습니다.

  1. Java 컬렉션 synchronizedMap() 메서드
  2. ConcurrentHashMap 사용

ConcurrentHashMap

  • 프로젝트에서 매우 높은 동시성이 필요할 때 ConcurrentHashMap을 사용해야 합니다.
  • whole map 을 동기화하지 않고도 스레드로부터 안전합니다.
  • 쓰기가 잠금으로 수행되는 동안 읽기는 매우 빠르게 발생할 수 있습니다.
  • 개체 수준에는 잠금이 없습니다.
  • 잠금은 해시맵 버킷 수준에서 훨씬 더 세밀합니다.
  • ConcurrentHashMap은 다른 스레드가 반복하는 동안 한 스레드가 수정을 시도하는 경우 ConcurrentModificationException 을 throw하지 않습니다.
  • ConcurrentHashMap은 다수의 잠금을 사용합니다.

동기화된 해시맵

  • 개체 수준에서 동기화.
  • 모든 읽기/쓰기 작업은 잠금을 획득해야 합니다.
  • 전체 컬렉션을 잠그면 성능 오버헤드가 발생합니다.
  • 이것은 본질적으로 전체 맵에 대한 하나의 스레드에만 액세스 권한을 부여하고 다른 모든 스레드를 차단합니다.
  • 다툼의 원인이 됩니다.
  • SynchronizedHashMap은 동시 수정 시 빠른 속도를 내는 Iterator 를 반환합니다.

이제 코드를 살펴보자

  1. CrunchifyConcurrentHashMapVsSynchronizedHashMap.java 클래스 생성
  2. 각 HashTable, SynchronizedMap 및 CrunchifyConcurrentHashMap에 대한 객체 생성
  3. 지도에서 500,000개 항목 추가 및 검색
  4. 시작 및 종료 시간을 측정하고 시간을 밀리초 단위로 표시
  5. ExecutorService를 사용하여 5 threads 를 병렬로 실행합니다.

다음은 자바 코드입니다.

  • shutdown() 은 실행기 서비스가 더 이상 들어오는 작업을 수행하지 않음을 의미합니다.
  • awaitTermination() 은 종료 요청 후에 호출됩니다.

따라서 먼저 serviceExecutor를 종료한 다음 차단하고 스레드가 완료될 때까지 기다려야 합니다.

Eclipse 콘솔 결과: