귀하의 방법은 스레드로부터 안전하지 않습니다 : 하나 개의 스레드 라인이 바뀌지
private static Map<Class<MyClass<?>>, MyClass<?>> s_instances =
new HashMap<Class<MyClass<?>>, MyClass<?>>();
public static MyClass<?> blah(Class<MyClass<?>> clz)
throws InstantiationException, IllegalAccessException {
if (s_instances.get(clz) != null)
return s_instances.get(clz);
// here1
MyClass<?> instance = clz.newInstance();
s_instances.put(clz, instance);
// here2
return instance;
}
되면이 //here1
표시, 첫 번째 스레드가 따라서 두 번째를 작성, //here2
표시 줄에 전에 두 번째 스레드가 방법을 입력 할 수 있습니다 같은 종류의 "싱글 톤"을 만들고지도의 첫 번째를 덮어 씁니다.
빠른-수정지도를 동기화하는 것입니다 :
public static MyClass<?> blah(Class<MyClass<?>> clz)
throws InstantiationException, IllegalAccessException {
synchronized(s_instances){
if (s_instances.get(clz) != null)
return s_instances.get(clz);
// here1
MyClass<?> instance = clz.newInstance();
s_instances.put(clz, instance);
// here2
return instance;
}
}
그러나, 많은 스레드가 결국 아마도 응용 프로그램을 죽이고, 많은 시간을 기다려야 할 것이라는 점을 의미 할 것입니다. 아마 당신이 할 일은 두 단계 솔루션입니다 :
private static Map<Class<MyClass<?>>, MyClass<?>> s_instances =
Collections.synchronizedMap(new HashMap<Class<MyClass<?>>, MyClass<?>>());
를하거나 함께 이동 : 또한
public static MyClass<?> blah(Class<MyClass<?>> clz)
throws InstantiationException, IllegalAccessException {
Object candidate = s_instances.get(clz);
if(clz.isInstance(candidate)){ // implicit null check
return clz.cast(candidate);
}
synchronized(s_instances){
Object candidate = s_instances.get(clz);
if(clz.isInstance(candidate)){ // gotta check a second time in a
return clz.cast(candidate); // synchronized context
}
MyClass<?> instance = clz.newInstance();
s_instances.put(clz, instance);
return instance;
}
}
당신이 Collections.synchronizedMap()
에 포장해야 하나, 그래서는 HashMap은 동시 액세스에 적합하지 않습니다 ConcurrentHashMap
대신
유형별로 별도의 인스턴스를 갖는 요지는 귀하의 경우에 분명하지 않습니다. 새 인스턴스는 MyClass의 정확한 생성자 (서브 클래스가 아님)이어야하므로 MyClass의 생성자를 호출 할 수 있습니다 (리플렉션 필요 없음). – artbristol