2013-06-25 3 views
0

다음과 같은 시나리오가 있습니다 : 여러 이벤트가 각각 다른 유형의 소스에서 제공됩니다. 나는 연속적으로 같은 유형의 각 사건으로 무언가를 할 필요가 있으며, 다른 유형이라면 병행하여 처리해야한다. 의미 소스쓰레드가 알림으로 깨어 나지 않았습니다.

이벤트 : A1, A2, B1, A3, B2, C1

  • 수신기 A, A1, A2와 A3을 대기해야하며, 즉 순서대로 작동 다른 스레드에 평행 한 B로서
  • 수신기 C 같은 다른 스레드 병렬 같은
  • 수신기 B와 동일한 단일 쓰레드
  • ,,,, I는 t를 실현하고있는 무슨

그의? 일반적인 용어로, 나는 새로운 스레드로 초기화 한 다음 wait()을 호출하는 각 이벤트 유형에 대한 모니터를 가지고 있습니다. 모든 모니터에는 대기열이 있습니다.

Monitor.java는

public void run(){ 
    while(!killed){ 
    synchronize(this){  
     while(this.stopped){ 
     wait(); //it waits here when initialized, waiting for the first event 
     } 

     while(eventQueue.size() > 0){ 
     //do something with the event 
     } 

     //i set the flag stopped = true again to wait for the next event 
     this.stopped = true; 
    } 
    } 
} 

이벤트가 도착, 난는 동안

public void awake(Event event){ 
    synchronize(this){ 
    eventQueue.add(event); 
    this.stopped = false; 
    notify(); 
    } 
} 

나누기 있도록 후) (모니터 통지 큐에 추가 (실행 가능한 구현) "killed"플래그는 특정 기준이 충족 될 때까지 스레드를 활성 상태로 유지하는 데 사용됩니다. 그런 다음 kill 플래그를 true로 설정하고 모니터에 스레드 종료를 알립니다.

제 문제는 일련의 이벤트를 실행할 때 가끔 스레드가 notify()로 깨어 나지 않는 경우입니다. 때로는 10 개의 이벤트 중 10 개가 처리되고, 때로는 10 개 중 8 개가 처리됩니다.

나는 내 문제에 대한 대안을 찾고있는 동시 API를보고 있었지만 좋은 것을 찾을 수는 없다. 이 문제에 어떻게 대처할 수 있는지 조언 해 주시겠습니까?

나는 좋은 방법으로 내 문제를 설명하고 싶습니다. 그렇지 않다면 물어보십시오.

미리 감사드립니다.

+0

FYI :'this.stopped'는 다중 스레드에서 사용되기 때문에 '휘발성'이어야합니다. – Gray

+0

'notify()'또는'notifyAll()'? – Raedwald

답변

5

"killed"플래그는 특정 기준이 충족 될 때까지 스레드를 활성 상태로 유지하는 데 사용됩니다. 그런 다음 kill 플래그를 true로 설정하고 모니터에 스레드 종료를 알립니다.

우선, LinkedBlockingQueue과 같은 BlockingQueue을 사용하도록 코드를 전환하는 것이 좋습니다. killed 플래그 (여전히 voltilebtw 여야 함)를 사용할 수 있지만 BlockingQueue을 사용하면 모든 신호가 처리됩니다. 당신이해야 할 일은 put()을 호출하여 대기열에 추가하고 take()을 읽는 것입니다. synchronized, wait 또는 notify을 사용할 필요가 없습니다. stopped 플래그가 전혀 필요하지 않습니다. 아래를 참조하십시오. 내가 이벤트 집합을 실행할 때

while (!killed) { 
    Event event = eventQueue.take(); 
    ... 

내 문제는 때로는 스레드가 통지에 깨어하지 않습니다,()이다. 때로는 10 개의 이벤트 중 10 개가 처리되고, 때로는 10 개 중 8 개가 처리됩니다.

현재 코드에 문제가있는 것으로 보아도 문제는 보이지 않지만 악마가 자세히 나와 있습니다. 한 가지 기억해야 할 것은 스레드 A가 notify()을 호출하면 스레드 B가 wait()이라고 호출하면 알림이 손실된다는 것입니다. 난 당신이 다음과 같이 뭔가를하고 싶은 생각 :

while(!killed){ 
    Event event; 
    synchronized (this) { 
     // wait until where is something in the queue 
     while(eventQueue.isEmpty()){ 
      this.wait(); 
     } 
     event = eventQueue.get(); 
    } 
    // work with event 
    ... 

이 유일한 방법 큐가 비어있는 경우가 stopped 부울을 필요로하지 않는 것입니다.

+0

대기열에 이벤트를 넣을 때 특별한 것을해야합니까? (호출 알림?) 또는 그냥 eventQueue.put (이벤트) 말하는 스레드를 깨어 것으로 추정됩니까? – GoVeM

+0

당신은 @GoVeM을 기다리고있을 때 소비자를 깨울'not()'을 호출하고'notify() '를 호출해야합니다. 'BlockingQueue'를 사용한다면'notify()'를 할 필요가 없습니다. – Gray

+0

사실 저는 여러분의 솔루션을'BlockingQueue'로 시도하고 있습니다. 그러나 이벤트를 넣었을 때 스레드는 여전히 대기 상태에 있습니다. – GoVeM

관련 문제