2012-01-17 4 views
3

나는 싱글과 같은 역할을하는 정적 필드를 포함하는 클래스가 있습니다수퍼 클래스의 정적 필드에서 액세스를 동기화하는 방법은 무엇입니까?

public class A { 

    private static MyAPI instance = null; 

    protected synchronized static MyAPI getAPI() throws Exception { 
     if (instance == null){ 
      // init API; 
     } 
     return instance; 
    } 

    // other methods 

} 

을 그리고는 클래스 A에서 상속과 API에 대한 작업을 수행해야하는 여러 클래스가 있습니다. 저는 멀티 스레드 환경에서 작업하며 API는 한 번에 한 번씩 작동하므로 모든 하위 클래스가 동시에 API에서 작동하지 않도록해야합니다. 나는 서브 클래스의 API에 액세스 할 때이를 위해, 나는 슈퍼 클래스를 동기화 :이 솔루션을

public class B extends A { 

    public void myMethod(){ 
     synchronized (A.class) { 
      myAPI = getAPI(); 
      // do stuffs with myAPI 
     } 
    } 
} 

을, 내가 대신 그냥 API 인스턴스의 전체 클래스를 잠 그려면, 그래서 내 A 급의 다른 방법은 없습니다 API 및 성능에 대한 하위 클래스 작업이 줄어들 때 사용할 수 있습니다.

이것이 최선의 해결책이라고 생각하십니까? 아니면 더 좋은 방법을 알고 있습니까?

감사합니다.

답변

1

는 전체 클래스에 고정하지 않으려면, 당신은 그 방법 만 사용하는 정적 객체를 잠글 수 있습니다

public class A { 

    private static MyAPI instance = null; 
    protected static Object lockForMyMethod = new Object(); //have a static lock 

    // other methods  
} 

public class B extends A { 

    public void myMethod(){ 
     synchronized (A.lockForMyMethod) { //do not lock on A.class 
      myAPI = getAPI(); 
      // do stuffs with myAPI 
     } 
    } 
} 
2

내가 여기 생각 하는데요 두 가지 문제가 있습니다 : MyAPI 객체가 단일 역할을하기 때문에

  1. 첫째, 다른 클래스는 클래스 A에서 상속 사실은 무관하다. 비 계층 적 구조의 다른 클래스가 싱글 톤을 참조하도록 할 수도 있습니다.

  2. 두 번째로 동기화는 MyAPI 코드 내에서 수행되어야하며 원하는 방식으로 동기화 세분성을 제어 할 수 있습니다. 이렇게하면 캡슐화가 더 잘 이루어지며 진행하기 전에 잠금을 얻지 못하는 나쁜 행동을하는 발신자에 대해 걱정할 필요가 없습니다. 그것은 예를 들어

등 기능에 따라, 방법에 따라 될 수 있습니다

class MyAPI { 

    public synchronized void doWork1() { // class level lock 
    ... 
    } 

    public void doWork2 { 
    synchronized (someLockObject) { 
     ... 
    } 
    } 

    public void doWork3 { // related to doWork2, lock the same object 
    synchronized (someLockObject) { 
     ... 
    } 
    } 
+0

두 번째 사항에 동의하지만 광산이 아니기 때문에 API를 수정할 수 없습니다! – alex88

+1

다음 장식 자 - 다른 싱글 톤으로 포장하십시오. – Yoni

0

나는 다중 스레드 환경에서 작업하고 API는 한 번에 한 번 사용할 수 있습니다, 그래서 동시에 모든 하위 클래스가 API에서 작동하지 않도록해야합니다.

환경에 따라 ExecutorService을 사용해보십시오.

예를 들어 고정 스레드 풀 크기가 1 인 ThreadPoolExecutor을 사용하여 해당 실행자에게 작업을 제출할 수 있습니다.

그런 식으로 API를 제출 한 Callable의 call() 메소드에서만 사용할 수 있습니다. 하나의 스레드 만 작동하므로 API의 동시 액세스에 대해 걱정할 필요가 없습니다.

또 다시, 나는 당신이 일하고있는 환경을 모른다. 어쩌면 나쁜 생각이거나 ExecutorService로 문제를 해결할 수 없다.

+0

그것은 내가하고 싶은 일을 위해 조금 복잡하지만 전혀 나쁜 생각이 아닙니다! – alex88

관련 문제