2011-02-14 7 views
2

싱글 톤 클래스에서 get/set/size 메서드를 사용하여 LinkedList를 보유하는 스레드 안전 이중 검사 Singleton 클래스가 있습니다. 그런 다음이 Singleton 클래스를 사용하여 객체 풀을 관리하는 간단한 풀 클래스가 있습니다.싱글 톤 클래스 메서드를 Java에서 스레드로부터 안전하게 보호하려면 어떻게해야합니까?

제 질문은 동기화 방법을 사용하지 않고 싱글 톤 및 풀 클래스에서 get/set 메서드를 어떻게 방어 할 수 있습니까? 내 코드는 다음과 같습니다

public class SingletonDoubleCheckedLockingPattern { 

    private static SingletonDoubleCheckedLockingPattern s = new SingletonDoubleCheckedLockingPattern(); 

    private LinkedList<Object> linkedList; 

    public int GetListObjectCount() { 
     return linkedList.size(); 
    } 

    public Object GetObjectFromList() { 
     return linkedList.poll(); 
    } 

    public void SetObjectFromList(Object ee) { 
     linkedList.add(ee); 
    } 

    private SingletonDoubleCheckedLockingPattern() { 

     linkedList = new LinkedList<Object>(); 

    } 

    /** 
    * SingletonHolder is loaded on the first execution of 
    * Singleton.getInstance() or the first access to SingletonHolder.INSTANCE, 
    * not before. 
    */ 
    private static class SingletonHolder { 
     public static final SingletonDoubleCheckedLockingPattern INSTANCE = new SingletonDoubleCheckedLockingPattern(); 
    } 

    public static SingletonDoubleCheckedLockingPattern getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 

    // avoid cloning 
    public final Object clone() throws CloneNotSupportedException { 
     throw new CloneNotSupportedException(); 
    } 

} 

public class SingletonObjectPool { 

    private int maxlistValue = 10; 


    public Object GetObject() 
    { 
     int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount(); 
     if(listCount > 0) 
     { 
      return SingletonDoubleCheckedLockingPattern.getInstance().GetObjectFromList(); 
     } 
     return null; 
    } 


    public void SetObject() 
    { 
     int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount(); 
     if(listCount < maxlistValue) 
     { 
      SingletonDoubleCheckedLockingPattern.getInstance().SetObjectFromList(new Object()); 
     } 

    } 


} 
+1

후자가 정확한 철자이므로 검색을 위해 참조를 "단일 톤"에서 "싱글 톤"으로 업데이트했습니다. –

+1

이중 확인 된 잠금 패턴을 사용하고 있지 않습니다. 이는 문제가 아닙니다. 클래스 내에서 하나와 홀더 내에서 두 개의 인스턴스를 생성합니다 ... – pgras

답변

2

스레드 안전 인 BlockingQueue을 사용할 수 있습니다. 요소를 제거하기 전에 컬렉션이 비어 있는지 여부를 확인할 필요가 없습니다. 컬렉션에는이를 수행 할 수있는 메소드가 있습니다.

코드를 단순화하고 스레드로부터 안전하게 만들 수 있습니다. 내가 생각할 수있는

public class SingletonObjectPool { 
    private static final int maxlistValue = 10; 
    private static final BlockingQueue queue 
     = new ArrayBlockingQueue(maxListValue); 

    public static Object getObject() { 
     return queue.poll(); 
    } 


    public static void addObjectAsRequired() { 
     queue.offer(new Object()); 
    } 
} 
0

유일한 방법이 할 수 있습니다 synchronized를 사용하지 않고 같은 GetListObjectCount 같은 가능 호출 방법, 목록 자체가 스레드 안전이 방법의 얼굴에 호출 될 때 현명하게 행동 할 경우입니다 동시 수정.

그런 경우 목록 자체에 대한 참조가 변경되지 않으므로 다른 문제는 발생하지 않습니다. 이 내용을 분명히하기 위해 final으로 선언하고 컴파일러에서 목록을 다시 할당하려고하는 사람에게 경고하도록 할 수 있습니다. (이것이 필수 사항이라면 참조는 적어도 volatile 일 필요가 있지만 클래스의 다중 조작의 정확성에 대한 다른 많은 질문을 제기합니다).

결론은 "스레드 안전성"이 단순한 2 진 개념이 아니라는 것입니다. 특정 클래스 및/또는 메서드가 스레드로부터 안전하다고 말할 수는 없습니다. 오히려 유용하고 올바른 의미로 호출 할 수있는 메소드의 조합에 관한 것입니다.

+0

또한'size()'를 검사하고'remove()'를 다음과 같이 수행하는 대신'poll()'과 같은 단일 메소드를 호출해야합니다. 당신은이 작업들 사이에서 경쟁 조건을 가질 수 있습니다.주의 : 코드를 더 간단하게 만드는 것이 안전합니다. ;) –

관련 문제