2014-02-06 5 views
4

매 시간마다 한 번씩 완전히 업데이트되는 하나의 큰지도에 크게 의존하는 웹 서비스를 작성하고 있습니다. 나머지 시간에는 많은 스레드가 동시에 테이블을 읽습니다.동시 읽기 전용 HashMap

제 질문은 : 그러한 맵을 실현하는 가장 효율적인 구조는 무엇입니까?

지도가 다소 커질 수 있습니다 (100 - 500MB). 전체지도가 대체되는 시간당 한 번만 제외하고 읽기 액세스 권한 만 있습니다.

자바 HashMap을 사용하고 성능을 향상 시키려면 리플렉션을 사용하여 업데이트 간의 필드를 최종적으로 설정하려고 생각했지만 많은 동시 읽기에 대해 JVM 최적화 방법을 모르는 경우가 있습니다.

+2

외부에서 'ReadWriteLock'을 통해 액세스를 관리 할 수 ​​있습니다. 그 외에도 "정상적인"HashMap보다 더 효율적으로 만들 계획입니까? – Marco13

+4

정상적인 HashMap으로 충분하지 않다는 증거가 있습니까? –

+0

내가 가장 두려워하는 점은 각 스레드마다 자체 복사본이 있다는 것입니다. 또한 ConcurrentHashMap에는 동시 작성을위한 장점이 있다는 것을 읽었습니다. – xgb84j

답변

14

지도가 사용되는 동안 업데이트되지 않으므로 HashMap을 사용하십시오. 이는 스레드 안전성을 희생하여 탁월한 O (1) 조회 성능을 제공합니다.

새로 고침이 끝나면 새지도를 만들고 참조를 바꿉니다.

스왑 스레드 안전 만들기 위해 AtomicReference 사용을 고려 : 새로운 맵에서

mapRef.get().get(key); 

초기화 또는 스왑 :

private final AtomicReference<Map<K, V>> mapRef = new AtomicReference<>(); 

사용에

Map<K, V> newMap = new HashMap<>(); 
// populate map 
mapRef.set(newMap); // all threads will see this change 
+0

이것도 제가 생각했던 것입니다! 하지만 "AtomicReference"사용에 대한 의미를 설명 할 수 있습니까? – xgb84j

2

당신의 시나리오에서 자바의 표준 HashMap이 충분히 빠르지 않다는 것을 증명할 때까지, 여기에 세계를 멈추게하면 문제가 될 수 있습니다.

항상 HashMap (매번 새로운 맵핑을 작성하지 않음)을 재사용하고 맵에 저장 한 모든 오브젝트를 사전 할당하고 재사용하여 문제를 피할 수 있습니다.

그 외에도 @Bohemian이 제시 한 답변과 같이 두 개의 HashMaps를 사용하여 더 빨리 대체 할 수 있습니다.

-1

사용하십시오.

public class Model { 
    private Map<?, ?> values; 
    private ReadWriteLock lock = new ReentrantReadWriteLock(); 

    public ? getValue(? key) { 
    lock.readLock().lock(); 
    ? rv = values.get(key); 
    lock.readLock().unlock(); 
    return rv; 
    } 

    public void update(Map<?, ?> values) { 
    lock.writeLock().lock(); 
    rv = values; 
    //OR rv.putAll(values) 
    lock.writeLock().unlock(); 
    } 
} 
1

이동 : ConcurrentHashMap. 성능 저하없이 동시 읽기 액세스가 가능합니다.

+0

http://stackoverflow.com/questions/1378310/performance-concurrenthashmap-vs-hashmap – dierre