2011-01-20 5 views
2

나는 이것으로 철저히 혼란 스럽다. 나는 단위 테스트의 전체 패키지를 실행 중입니다. 여기에 JUnit 테스트들에 의해 관련 공유 코드 사용됩니다있어 어떤 :HashMap containsKey()가 String을 키로 사용하지 못하게 할 수있는 원인은 무엇입니까?

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

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException { 
    JAXBContext context = null; 
    if (jaxbContexts.containsKey(clazz.getName())) { 
     context = jaxbContexts.get(clazz.getName()); 
    } else { 
     context = JAXBContext.newInstance(clazz); 
     System.out.println("Created new context for '" + clazz.getName() + "'"); 
     jaxbContexts.put(clazz.getName(), context); 
    } 
    return context; 
} 

의 JUnit 실행에서 콘솔 출력은 다음과 같은 두 개의 연속적인 항목을 포함 : 나는 무엇을 놓치고

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 

를? jaxbContexts.containsKey()이 JUnit 실행 중 다른 46 번과 달리 String 기반 키에 대해이 인스턴스에서 작동하지 않는 이유는 무엇입니까? 우리는 테스트를 평행하게 진행하지는 않지만 차이가 나는 경우에는 측면을 사용합니다.

+0

두 줄 사이에 JVM을 중지/시작하지 않았습니까? – Pointy

답변

3

디버그와 본 getJAXBContext() 메소드를 포함하는 클래스는 (그것이 모든 호출에 대한 디버그 모드에서 동일한 메모리 ID를 가지고있어 확인하여) 한 번만 인스턴스화되어 있는지 확인합니다. 인스턴스화가 다른 경우 synchronized 키워드는 다른 잠금에 대해 잠금을 설정하며 다른 맵을 사용합니다.

+0

감사합니다. 디버깅은 정적 jaxbContext의 인스턴스가 두 개 이상 있는지 확인합니다. 이 코드는 추상 구현 클래스가 여러 개있는 추상 클래스입니다. 서브 클래스 당이 필드의 정적 인스턴스가 하나 있습니까? –

+0

@Chris, 그 질문에 대답한다면, 받아들이십시오. –

+0

이 메서드는 정적이 아니므로 객체 인스턴스에서 동기화됩니다 (클래스 인스턴스가 아닌 다른 잠금을 제공하므로 잠금을 제공하지 않습니다). 맵은 정적이지만 잠금없이 동시에 사용되므로 포함 된 시간 사이에 맵이 추가되고 추가 될 때 다른 스레드가 이미 동일한 키에 대해 동일한 작업을 수행 할 수 있습니다. sychronized (jaxContents) {여기 모든 코드}를 사용하면 효과가있을 수 있습니다. –

1

개인적으로, 나는 containsKey를 신경 쓰지 않을 것입니다.

String name = clazz.getName(); 
context = jaxbContexts.get(name); 
if (context == null) { 
    context = JAXBContext.newInstance(clazz); 
    System.out.println("Created new context for '" + name + "'"); 
    jaxbContexts.put(name, context); 
} 
+0

그렇지만 containsKey가 작동하고 실제로 jaxbContexts의 여러 정적 인스턴스에 문제가 있음을 나타내는 결과에는 영향을 미치지 않습니다. –

+0

예, 실제로이 문제를 해결하지 못한다는 것을 알고 있습니다. 그래서 제가 제프리의 대답에 투표했습니다. –

0
경주를 제외하고

...하지만 당신은 당신이 병렬로 일을 실행하지 않는 것이 말 ...

어쨌든, 난 context = jaxbContexts.get(clazz.getName())을 불러 null에 대해 context을 테스트 한 것입니다. 두 개 이상의 클래스가 같은 이름을 가질 수 있기 때문에

아, 그리고지도 키로 문자열을 포함하는 특별한 아무것도 확실히 없다

+0

감사합니다. 원래 클래스 자체를 키로 사용했지만 클래스 이름으로 전환하면서이 문제의 맨 아래로 가려고했습니다. –

1

(클래스 로더를 생각한다), 키로 클래스 자체를 사용했다. println을 new Exception().printStackTrace()으로 바꾸면 무슨 일이 일어나는지보실 수 있습니다. 지도를 보유하고있는 클래스의 인스턴스 두 개를 만들거나 다른 것을 만들 수 있습니다.

-1

쉬운 사용을 위해 Map<String, JAXBContext> 대신 Map<Class, JAXBContext> 일 수 있습니다.