2011-01-27 7 views
1

루프에서 일부 청취자에게 통지합니다.청취자를 호출 할 때 허용되는 최대 처리 시간을 적용하십시오.

for (Iterator it = listeners.iterator(); it.hasNext();) { 
    MyListener l = (MyListener) it.next(); 
    l.notifyEvent(event); 
} 

나는 리스너가 통지 방법에서 무엇을하고 있는지 전혀 모른다 - 아주 오래 걸릴 수 있습니다 또는 입력을 기다리고 차단. 시스템의 응답 성을 보장하기 위해 다음 청취자와 계속 진행하기 전에 최대 처리 시간을 허용하려고합니다.

메서드 호출을위한 최대 처리 시간을 보장하기 위해 허용되는 패턴은 무엇입니까?

  • 산란 신고를위한 새 스레드 :

    나는 두 가지 가능성을 생각. 시간 내에 돌아 오지 않으면 새 스레드를 만들고 다음 스레드를 처리하십시오. 결국 첫 번째 사람이 돌아 오면 그냥 그냥 내버려 둬. 이 전략에 대한 코드 예제를 제공 할 수 있습니까?

  • 현재 처리중인 리스너 스레드에 인터럽트를 보내고 이것이 리턴하게되기를 바랍니다.

다른 아이디어 또는 모범 사례?

추 신 : Java 1.4와 함께 java.util.concurrent 백 포트를 사용하므로 j.u.c 구문을 사용할 수 있습니다.

편집 : 여기 내가 개발 한 해결책이 있습니다. ExecutorServices를 사용하므로이 간단한 목적을 달성하는 데 약간 무거움. 이 스레드는 해당 스레드가 수신기에서 멈추기 전까지 하나의 추가 스레드 만 사용합니다. 그런 다음 새 스레드 (새 ExecutorService에 있음)를 생성하여 다음 리스너와 함께 작업합니다. 참고 :이 솔루션은 스레드 안전성이나 동시성을 지원하지 않습니다. 하나 개의 스레드가 doNotify()

private final Queue listeners = new ConcurrentLinkedQueue(); 
private final long timeout; 
private final TimeUnit unit; 
private ExecutorService threadPool = Executors.newFixedThreadPool(1); 

public void doNotify(){ 
    for (Iterator it = listeners.iterator(); it.hasNext();) { 
     final MyListener l = (MyListener) it.next(); 
     Future future = threadPool.submit(new Runnable() { 
      public void run() { 
       l.notifyEvent(); 
      } 
     }); 
     try { 
      future.get(timeout, unit); // wait for task to be executed 
     } catch (InterruptedException e1) { 
      // ignore for now 
     } catch (ExecutionException e1) { 
      // ignore for now 
     } catch (TimeoutException e1) { 
      threadPool.shutdown(); // pool accepts no new tasks, and will exit when done 
      threadPool = Executors.newFixedThreadPool(1); // make new thread for next listener 
     } 
    } 
} 

답변

1

청취자가 독립적 인 경우를 호출해야합니다, 당신은 자신의 "응답"또는 콜백 신경 쓰지 않는 경우에, 당신은 단순히 청취자에게 통지 각 청취자에 대한 스레드를 생성 할 수있다 . 계속 진행하기 전에 번을 끝내기까지 시간을으로 지정하려면 각 스레드에서 Thread.join(millis)으로 제한 시간을 호출 할 수 있습니다.

최대 스레드 수를 신경 쓰면 동일한 접근 방식을 사용할 수 있지만 대신 스레드 풀을 사용할 수 있습니다. 그러나 "블로킹"리스너의 수가 스레드 풀의 스레드 수를 초과하면 약간의 문제가 발생합니다.

Thread.stopgood reasons에 대해 사용되지 않습니다.

+0

입력 해 주셔서 감사합니다. 나는 그것을 기반으로 할 것입니다. 많은 청취자의 경우 솔루션에서 피하고자하는 많은 스레드가 생성됩니다. 새 스레드는 필요한 경우에만 만들어야합니다 (정상적인 리스너가 정시에 응답한다고 가정). – Philipp

+0

@ Philipp, 그 이유는 대안 설계 선택 사항으로 스레드 풀을 언급했기 때문입니다. – aioobe

0

리스너의 코드를 제어하지 않으므로 대부분의 리스너는 이벤트 발송 스레드에서 실행되고 있다는 가정하에 작성됩니다. 백그라운드 스레드에서 실행하면 스레드로부터 안전하지 않은 AWT 또는 Swing 메소드가 호출 될 수 있습니다.

당신이 제어하는 ​​특정 MyListener 인터페이스로 제한되어 있다면 적어도 MyListener.notify()이 EDT에서 호출되지 않을 것이라고 javadoc에주의해야합니다.

+0

* "대부분의 청취자는 이벤트 발송 스레드에서 실행되고 있다는 가정하에 작성됩니다."* ... AWT/Swing 청취자에 대해 이야기하고 있다고 가정합니까? – aioobe

+1

내 질문에 대한 일반적인 스레딩/AWT 스레딩에 대한 것입니다. 그에게 중요한 것이 있다면 리스너는 무엇을하기 전에 스레드가 그것을 호출하는지 확인할 수 있습니다. – Philipp

+0

오케이, 죄송합니다. 나는 당신이 스레드를 막는 것을 피하고 청취자가 참여했다면, 문제의 스레드가 EDT이고 청취자가 AWT/Swing 이벤트 리스너라는 것이 좋았다. 결론에 이르면 죄송합니다. –

1

설명을 위해 : MyListener 코드를 제어하지 않으면 (새 스레드를 생성하더라도) 낭비하는 시간을 제어 할 수 없습니다. 쓰레드가 강제로 종료되거나 인터럽트되거나, 허용 된 시간을 존중할 수있는 방법은 없습니다.

+0

* 스레드를 강제로 종료 할 수있는 방법은 없습니다. * 글쎄,'Thread.stop' 메서드가 있지만 극단적으로주의해서 사용해야합니다 (있는 경우). – aioobe

+0

'Thread.stop'은 더 이상 사용되지 않아야합니다. –

+0

Thread.stop은 쓰레드를 죽이고 "리소스를 해제하는 방법"을 모른다면 아무 것도 누출 될 수 있기 때문에 더 이상 사용되지 않습니다. MyListener의 코드를 제어하지 않고 스레드를 종료하면 잃을 수도있는 것을 예측할 수 없습니다. 그리고 그것은 중요한 것이어야합니다 :) –

관련 문제