각 스레드에 대해 정확히 하나의 클래스 인스턴스를 생성하는 인스턴스 팩토리를 작성하는 좋은 방법을 찾고 있습니다 (즉, 스레드 특정 싱글 톤).스레드 특정 싱글 톤 인스턴스
가 이 첫째, 일반적으로 공장 정의하는 인터페이스: 일반 싱글 들어
public interface Factory<T> {
public T create();
}
, 나는 다음이 인터페이스의 구현을 만들 수는 랩
나 명확성을 위해 몇 가지 예제 코드를 추가하자 또 다른 공장 :
public class SingletonFactory<T> implements Factory<T> {
private final Factory<T> factory;
private T instance = null;
public SingletonFactory(Factory<T> factory) {
this.factory = factory;
}
@Override
public T create() {
if (instance==null) instance = factory.create();
return instance;
}
}
기본적으로, create()
를 호출 할 때 처음으로,이 호출이 CRE에 제공된 공장에 전달된다 객체의 한 인스턴스를 먹었습니다. 이 인스턴스는 캐시되고 create()
에 대한 이후의 모든 호출은 동일한 인스턴스를 반환합니다. 내가해야 할 일은 객체 유형 T
주위에 SingletonFactory
인스턴스가 하나만 있는지 확인하는 것입니다.
public class ThreadSingletonFactory<T> implements Factory<T> {
private final Factory<T> factory;
private final Map<Thread, T> instance;
public ThreadSingletonFactory(Factory<T> factory) {
this.factory = factory;
this.instance = new HashMap<Thread, T>();
}
@Override
public T create() {
Thread thread = Thread.currentThread();
T result = instance.get(thread);
if (result==null) {
result = factory.create();
instance.put(thread, result);
}
return result;
}
}
이제 때마다 create()
가 호출, 클래스가 현재 스레드를 조회 : 나는 이런 식으로 뭔가를 할 수 :
의 내가 스레드 당 객체 정확히 하나 개의 인스턴스를 제공하고자한다고 가정 해 봅시다 이 스레드가 이미 인스턴스가 생성되었는지 확인하기 위해 인스턴스 맵에 추가합니다. 그렇지 않으면 신선한 것을 만들고 그것을 기억합니다.
- 의 HashMap, 두 개의 스레드가 지금 같은 키가 작동하지 않습니다 때문에 문제가되지 않을 수도 있습니다 스레드로부터 안전하지 않습니다,하지만 난 아니에요 :
나는이 순진한 접근 방식에 문제가 몇 참조 확실한. 난 그냥
Collections.synchronizedMap
안전하게 스레드를 만들 수 있지만 중요한 영향을 미칠 수있는 모든 곳에서 동기화 톤을 의미하기 때문에 나는 그것을 피하고 싶습니다. - 응용 프로그램이 스레드 풀을 사용하지 않고 수명이 짧은 새 스레드를 계속 생성하는 경우지도가 잠재적으로 막대한 크기로 커지고 오래 걸리지 않는 인스턴스로 많은 메모리가 차단됩니다. 그것의 항목이 키가 더 이상 사용되지 일단 수집되지 쓰레기 할 수 있기 때문에
나는, 두 번째 문제를 해결하는 대신 WeakHashMap
을 사용하여에보고 있었다,하지만 난 그뿐만 아니라 두 개의 잠재적 인 문제를 건너 왔어요 : OpenJDK Source
보면
- ,
expungeStaleEntries()
를 통해 사용되지 않는 키의 해방 내가get(...)
또는put(...)
를 호출하고, 다시, 나는 성능상의 이유로 회피하고자하는 잠재적으로 여러 동기화 작업을 포함 할 때마다 시작됩니다. - 아직 동시성 문제가 발생하지 않도록하기 위해 synchronizedMap에 맵을 래핑 할 필요가 없다는 것이 확실하지 않습니다.
바람직하게 사용할 필요가없는 다른 용액 거기 임의synchronization
(가정 Factory.create()
모든 구현 스레드 안전 있음)? 어쨌든 동시성을 관리해야하는 경우 java.util.concurrent.atomic
의 클래스를 통해 그렇게하는 것이 좋습니다.
http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html –
당신이 스레드 특정 개체를 할 때마다, ThreadLocal''로 본다. –
@JBNizet, SotiriosDelimanolis, 귀하의 의견을 답변으로 바꾸려면 크레딧을 지불해야하는 크레딧을받을 수 있습니다. 당신이 옳은 해결책을 찾은 것 같아서요. –