2013-02-28 2 views
0

아래 코드에서 높은 처리량 환경에서 정적 메서드 getCustomerIdByClientKey이 여러 스레드에 사용됩니다.다른 스레드가 맵을 참조하는 동안 해당 맵에 대한 참조를 재 할당하면 예외가 발생합니까?

정적 메서드 loadCustomers은 매 10 분마다 호출되어 캐시를 무효화하고 새로운 고객 집합을로드합니다. 고객을 추가하거나 삭제할 수 있습니다. 이 재 할당 될 때 스레드가 현재 clientKeyToCustomerId지도를 사용하고 해당 스레드는 예외가 발생합니다, 또는 문제없이 그것의 메모리 공간에서 계속됩니다

나에 대해 걱정 라인은 clientKeyToCustomerId = newClientKeyToCustomerId;

입니다 , 또는 그것은 전체 JVM을 죽일 것인가? :)

성능에 부정적인 영향을 미칠 것으로 생각하여지도에 액세스하는 블록을 동기화하고 싶지 않습니다.

을 간단히 호출하고 싶지는 않습니다. 조회에 액세스하는 스레드는 검색 결과를 가져올 때 null 결과를 반환합니다.

지도를 바꾸면 문제가 발생할 수 있지만이를 해결하기위한 접근 방법은 무엇입니까? 휘발성에 읽어하라고 된 후

package com.mycompany.key; 

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import com.mycompany.dao.CustomerDao; 
import com.mycompany.model.Customer; 

public class CustomerManager { 

    private static Map<String, String> clientKeyToCustomerId = 
        new HashMap<String, String>(); 

    public static void loadCustomers() { 
     List<Customer> allCustomers = new CustomerDao().loadAll(); 
     Map<String, String> newClientKeyToCustomerId = new HashMap<String, String>(); 
     for (Customer customer : allCustomers) { 
      newClientKeyToCustomerId.put(customer.getActiveKey1(), 
        customer.getCustomerId()); 
      newClientKeyToCustomerId.put(customer.getActiveKey2(), 
        customer.getCustomerId()); 
     } 
     clientKeyToCustomerId = newClientKeyToCustomerId; 
    } 

    public static String getCustomerIdByClientKey(String pClientKey) { 
     return clientKeyToCustomerId.get(pClientKey); 
    } 

} 
+1

이전에 'clientKeyToCustomerId' 값 또는 업데이트 된'newClientKeyToCustomerId' 값을 가지고 있기 때문에 확실히 스레드를 죽이지는 않습니다. 나쁜 JVM 결함 만 있으면 JVM이 종료됩니다. 문제는 당신이 메모리 장벽을 넘지 않기 때문에 새로운 스레드가'newClientKeyToCustomerId'의 완전히 초기화 된 버전을 볼 것인지 아닌지에 있습니다. – Gray

+2

사실, 다른 스레드는 업데이트 된 맵을 전혀 볼 수 없을 것입니다. 최소한 변수를 휘발성으로 만들어야합니다. 동시 수집 사용을 고려해야합니다. – Perception

+0

휘발성에 대한 솔직히 올라간다 – Will

답변

1

, 나는이 질문에 허용 대답이 Volatile HashMap vs ConcurrentHashMap를 해결한다 생각합니다. 아래 코드를 수정했습니다. volatile 키워드는 스레드에 로컬로 캐시하는 모든 스레드를 중지합니다.

현재 기존지도에서 읽는 모든 스레드는 오래된 것입니다.하지만 비즈니스 관점에서는 괜찮습니다.

package com.mycompany.key; 

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import com.mycompany.dao.CustomerDao; 
import com.mycompany.model.Customer; 

public class CustomerManager { 

    //private static Map<String, String> clientKeyToCustomerId = 
    // new HashMap<String, String>(); 
    private volatile static Map<String, String> clientKeyToCustomerId = 
       new HashMap<String, String>(); 

    public static void loadCustomers() { 
     List<Customer> allCustomers = new CustomerDao().loadAll(); 
     Map<String, String> newClientKeyToCustomerId = new HashMap<String, String>(); 
     for (Customer customer : allCustomers) { 
      newClientKeyToCustomerId.put(customer.getActiveKey1(), 
        customer.getCustomerId()); 
      newClientKeyToCustomerId.put(customer.getActiveKey2(), 
        customer.getCustomerId()); 
     } 
     clientKeyToCustomerId = newClientKeyToCustomerId; 
    } 

    public static String getCustomerIdByClientKey(String pClientKey) { 
     return clientKeyToCustomerId.get(pClientKey); 
    } 

} 
관련 문제