2012-08-14 5 views
2

나는 제작자와 소비자 스레드 사이에 공유 버퍼를 쓰려고했다. 여기 내 코드는 다음과 같습니다.Java 스레드간에 공유 버퍼를 구현하는 방법은 무엇입니까?

class PQueue 
{ 
    Token token; 
    boolean flag = false; // false: add, true: poll 

    PQueue() 
    { 
     token = null; 
    } 

    synchronized void add(Token token) 
    { 
     if(flag == true) 
     { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     flag = true; 
     notify(); 
     this.token = token; 
    } 

    synchronized Token poll() 
    { 
     if(flag == false) 
     { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     flag = false; 
     notify(); 
     return this.token; 
    } 
} 

저는 멀티 스레딩을 처음 사용합니다. 잠재적 인 동시성 버그가 있습니까? 이 목표를 달성하기위한 "표준/공통"방법입니까? 아니면 더 간단하고 효율적인 방법이 있습니까?

+1

그냥 java.util.concurrent.BlockingQueue를 사용할 수 없습니까? – vanza

+0

동기화 된 블록 내부의'notify()'는 의심 스럽습니다. (작동하는지 또는 교착 상태가되는지 알 수 없습니다) –

+1

@Andreas_D : 다른 방법으로는 notify()를 호출 할 수 없습니다. 의심 많은? (그의 코드는 다른 이유로는 의심 스럽지만 그 코드는 아닙니다.) – vanza

답변

3

java.util.concurrent 패키지, 특히 BlockingQueue 인터페이스와이를 구현하는 클래스를 살펴보십시오. 이것은 한 스레드에서 다른 스레드로 메시지를 전달하기위한 것입니다. SynchronousQueue은 정확히 구현하려는 것입니다.

구현 자체에는 몇 가지 결함이 있습니다. 하나의 스레드에 대한 변경 사항을 다른 스레드에서 볼 수 있도록 공유 변수를 모두 volatile으로 선언해야합니다. 그리고 if (flag == false)if (flag == true) 테스트는 실제로 루프 여야합니다. 왜냐하면 wait()wake up spuriously 일 때 notify()이 실제로 호출되지 않았기 때문입니다.

별도의 플래그 변수를 사용하는 대신 오브젝트가 없음을 나타 내기 위해 토큰을 null로 설정하는 것이 좋습니다. 잡기, 인쇄 및 맹목적으로 계속해서 InterruptedException을 계속 수행하는 대신, 두 가지 방법 모두가 발생하면 예외를 throw하는 것이 좋습니다. 이것들은 블로킹 메서드이며, 블로킹 메서드가 중단 될 가능성을 처리하는 것은 호출자의 책임입니다.

또한 귀하의 Token 클래스가 무엇인지 모르겠지만 실제로 대기열에있는 유형은 해당 유형에 따라 다릅니다. 일반 PQueue<T>을 정의한 다음 토큰을 전달하려면 PQueue<Token>을 사용하는 것이 좋습니다.

1

java.util.concurrent 패키지의 thread-safe 클래스 및 인터페이스를 사용해보십시오.

2

ArrayBlockingQueue Class와 함께 BlockingQueue Interface를 사용합니다.

관련 문제