2014-10-16 2 views
0

이 코드를 이전 개발자 (lol)로부터 상속 받았다. 청취자 종류의 콜백을 사용하는 대신 조인을 지원하도록 변경하는 것을 고려하고 있습니다.청취자 대 참여자가있는 싱글 톤

내 요구 사항 : 1. DoMath 클래스 스레드가 완료 될 때까지 호출 스레드를 대기시켜야합니다. 2. 다른 스레드가 호출하지 못하도록해야합니다. 다른 스레드에서

(수업) - :이 호출 할 때

DoMath.getInstance().performMathCalc(); 

그것은 기다리거나 물론 잠을하지 않습니다 그래서

public class DoMath { 
    protected math calc() { 
    } 

    public static DoMath getInstance() { 
     if(_instance == null) { 
      _instance = new DoMath(); 
     } 

     return _instance; 
    } 

    // perform a synchronous math calc, and return a boolean indicating success or failure. 
    public boolean performMathCalc() { 
     MathEngine.setApplicationMode(MathEngine.AUTO); 
     MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION); 
     return true; 
    } 

    // perform an async math calc, and call back the listener when done 
    public void performMathCalc(final listener client) { 
     Thread mathThread = new Thread(new Runnable() { 
      public void run() { 
       boolean result = performMathCalc(); 
       client.mathFinished(result); 
      } 
     }); 
     mathThread.setDaemon(true); 
     mathThread.start(); 
    } 

    public static interface listener { 
     public void mathFinished(boolean success); 
    } 

    protected static DoMath _instance; 
} 

을, 그냥를하는 것이 좋습니다 리스너를 사용하거나 호출 클래스에서 조인을 구현할 수 있습니까?

+1

메인 스레드를 대기, 절전, 가입 또는 차단하지 않습니다. 이제까지. – njzk2

+0

@ njzk2 "항상"을 "비동기 *로 광고되는 작업을 수행 할 때"로 변경하면 좋은 조언이됩니다 (이 경우에는 확실히 적용됩니다). –

+0

aysnc 코드에는 버그가있을 수 있습니다. 리스너는 performMathCalc를 호출 한 스레드에서 호출되지 않고 대신 백그라운드 스레드에서 호출됩니다. – cyngus

답변

1

DoMath 클래스 스레드가 완료 될 때까지 호출 스레드를 대기시켜야합니다.

이미 가지고 있습니다. 다음 결과를 반환,

  1. 첫 번째 방법은 인수를 취하지 않고 호출 스레드에서 계산을 수행 performMathCalc 방법이 얼마나 있습니다. 이것은 귀하의 첫 번째 요구 사항을 충족시킵니다.

  2. 두 번째 방법은 비동기 래퍼 첫 번째 방법입니다. 호출자가 계산을 시작한 다음 미래의 어느 시점에서 작업이 완료되었다는 사실을 누군가에게 알리는 이해가있는 다른 작업을 수행 할 수 있습니다. 이것은 유용한 기능이므로 계속 사용하겠습니다.

나는 그러나, 비동기 래퍼 하나의 문제를 참조하십시오 리스너가 핵심 performMathCalc() 방법은 예외가 발생하는 경우 통보되지 않습니다. try/catch/finally 블록을 사용하여 오류가 발생하더라도 리스너가 항상 알림을 받도록하십시오. 청취자에게 두 번째 콜백을 추가할지 (예 : mathFailed) 또는 오류가 발생하면 mathFinished(false) 번으로 전화 할 것인지 결정해야합니다.

다른 스레드에서 호출하지 못하도록해야합니다.

비동기 버전은 단순히 동기 버전을 위임하기 때문에 동기 버전 만 잠글 필요가 있습니다. 또한

public synchronized boolean performMathCalc() { 
    MathEngine.setApplicationMode(MathEngine.AUTO); 
    MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION); 
    return true; 
} 

당신이 상호 배타적이지 작업의 다른 종류를 수행하려면 DoMath 클래스를 확장 끝날 경우 : 당신의 클래스는 하나 개의 논리적 기능을 제공하기 때문에 가장 간단한 방법은, synchronized 같은 방법을 표시하는 것 조작 특정 잠금에서 동기화 할 수 있습니다.당신의 싱글 접근으로 우리를 잎

:

public static DoMath getInstance() { 
    if (_instance == null) { 
     _instance = new DoMath(); 
    } 
    return _instance; 
} 

이 조건 초기화가 하지 스레드 안전합니다. 귀하의 싱글 톤은 매우 단순하며 초기 초기화 비용이 없기 때문에 _instancefinal static으로 표시하고 선언에서 초기화하십시오.

+0

나는 세 가지 모두를 상향 've다. 왜냐하면 각각은 내가 사용할 수있는 두드러진 테이크 어웨이를 가지고 있기 때문이다. 이 스레드가 안전한지 궁금 해서요, 지금은 그렇지 않습니다. 내가 더 많이 또는 더 적은 uhhmmmm ios 백그라운드 처리 (푸시없이 예측할 수없는)로 변했다는 것을 몰랐습니다. 고마워. 최종 정적 인스턴스에서 콜백으로 이동. 고맙습니다!!! (놀랍게도 이것에 상향 회의가 없었지만 내 마음에는 상향 줄이 답이었습니다. 다시 한 번 감사드립니다!) –

1

다른 하나가 완료 될 때까지 스레드를 일시 중지 하시겠습니까? 결코 주 스레드를 차단해서는 안됩니다.

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing, 

t.join(); 
causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify. 

또한

(자바 워드 프로세서), performMatchCalc()는 공개 할 필요가 있는가?

자 이제 코드가 실제로 올바르게 보이지만 다른 계산을 시작하지 못하게 할 수 있습니다. 아마도이 비슷한 뭔가 :

public static DoMath getInstance() { 
    if(_instance == null) { 
     _instance = new DoMath(); 
    } 

    return _instance; 
} 

스레드로부터 안전하지 않습니다 :

public class DoMath { 
     private Thread mathThread; 

     protected math calc() { 
     } 

     public static DoMath getInstance() { 
      if(_instance == null) { 
       _instance = new DoMath(); 
      } 

      return _instance; 
     } 

     // perform a synchronous math calc, and return a boolean indicating success or failure. 
     public boolean performMathCalc() { 
      if(null != mathThread && mathThread.isAlive()) 
       return false; 

      MathEngine.setApplicationMode(MathEngine.AUTO); 
      MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION); 
      return true; 
     } 

     // perform an async math calc, and call back the listener when done 
     public void performMathCalc(final listener client) { 
      //re-start calculation? if so 
      if(null != mathThread && mathThread.isAlive()) { 
       matchThread.interrupt(); 
       matchThread = null; 
      } 


      mathThread = new Thread(new Runnable() { 
       public void run() { 
        boolean result = performMathCalc(); 
        client.mathFinished(result); 
       } 
      }); 
      mathThread.setDaemon(true); 
      mathThread.start(); 
     } 

     public static interface listener { 
      public void mathFinished(boolean success); 
     } 

     protected static DoMath _instance; 
    } 
1

는이 점에 유의 마십시오. 클래스가 정말로 (자신의 ClassLoader를 기준으로) Singleton인지 확인하려면 해당 메서드를 동기화하거나 _instance 멤버를 초기화해야합니다. 어느 경우 든 _instanceprivate 또는 final이거나 둘 모두 여야합니다. 실제 요구 사항에 관해서는

,

(1) 당신이 동기 하나에 비동기 호출을 변경하거나, 주위 동기 래퍼를 넣어 할 것 같다. 후자는 기존 리스너 인터페이스를 통해 수행 할 수 있습니다. 그러면 비동기 작업 수행 기능이 유지됩니다. 합류하는 대신 연결을 원하지 않는다면, 새로운 쓰레드를 시작하는 것을 건너 뛰십시오 : 단지 현재 쓰레드에서 계산을 실행하십시오.

(2) 여러 스레드가 동시에 계산을 실행하지 못하게하는 방법은 부분적으로 문제 (1) 문제를 해결하는 방법에 따라 다릅니다. 모든 것을 동기화하면 DoMath.performMathCalc()을 동기화 된 방법으로 만 만들 수 있습니다. 비동기 계산 옵션을 유지한다면, 당신을 도울 수있는 클래스를 위해 java.util.concurrent.locks 패키지를 찾을 수 있습니다.

관련 문제