2011-04-06 4 views
6

ThreadPoolExecutor를 사용하여 Java 응용 프로그램에서 작업을 실행하고 있습니다. 나는 Executor 큐에서 어떤 시점에서 큐의 활성 작업의 수를 얻고 자하는 요구 사항을 가지고 있습니다. ThreadPoolExecutor에 대해 javadoc을 찾아 보았고 두 가지 관련 메서드 인 getTaskCount()getCompletedTaskCount()을 발견했습니다.ThreadPoolExecutor를 사용하는 활성 작업 수

설명서에 따라 위의 두 가지 방법 각각에서 예약 된 작업 수와 완료된 작업 수를 얻을 수있었습니다. 그러나 어떤 시점에서든 큐의 활성 작업 수를 얻기위한 솔루션을 찾을 수 없습니다. 나는 다음과 같이 할 수 있습니다 :

getTaskCount() = getCompletedTaskCount() + failed tasks + active tasks 

그러나 실패한 작업의 수는 의도 한 계산에 도달하기 위해 직접 사용할 수 없습니다.

여기에 뭔가가 있습니까?

+5

명세서 ("대기열에있는 활성 작업") 자체 모순 : 당신은 "활성 작업"또는 "대기열에있는 작업"원하는가? 대기열의 작업이 활성 상태가 아니기 때문에 대기열에 있습니다. –

+0

또한 "실패한 작업"이 의미하는 바를 명확히 할 수 있습니까? 실패를 구성하는 것은 전적으로 당신에게 달렸습니다. ThreadPoolExecutor는 실제로 스레드가 완료되었거나 실행 중 일부 (비 비즈니스 로직) 시스템 오류가 발생했다는 개념만을 가지고 있습니다. 반환 상태를 확인하거나 확인 된 예외를 잡아 실패를 판단해야하는 경우에는 ['Future'] (http://download.oracle.com/javase/6/docs/api/java/util/concurrent)를 사용해야합니다. /Future.html). –

+0

요구 사항에 대해 정확하지 않은 것에 대해 사과드립니다. 나는 기본적으로 예정된 작업 수를 찾고 있지만 런타임에 완료되지 않은 작업 수를 찾으려고합니다. 그리고 나는 "실패한 작업"을 예정된 작업으로 간주하지만 오류로 인해 성공적으로 완료하지 못했습니다. – invinc4u

답변

19

사용하려는 계산에 실패한 횟수를 알 필요가 있다고 생각하지 않습니다.

long submitted = executor.getTaskCount(); 
long completed = executor.getCompletedTaskCount(); 
long notCompleted = submitted - completed; // approximate 

(대략) 충분할 것입니다.


또는, size()getQueue()를 사용할 수 있습니다

int queued = executor.getQueue().size(); 
int active = executor.getActiveCount(); 
int notCompleted = queued + active; // approximate 

이 대답은 당신이 "아직 완료되지"수를 찾고있는 가정. 당신의 질문은 모순되어서 당신이 무엇을 요구하는지 완전히 확신하지 못합니다. 귀하의 질문에 대한 나의 코멘트에 답글이 틀리면, 그에 따라이 답변을 업데이트하겠습니다.

+0

두 번째 솔루션은 내가 찾고있는 솔루션이었습니다. 당신의 도움을 주셔서 감사합니다. – invinc4u

+0

일부 Queue 구현은'size()'메소드에 대한 O (1) 연산을 지원하지 않으며 예상보다 오래 걸릴 수 있음을 기억하십시오. – user482594

4

beforeExecute 및 afterExecute 메서드를 사용해 보셨습니까? 이들은 작업이 실행되기 전후에 호출됩니다. after execute 메서드는 throwable을 두 번째 인수로 제공하기 때문에 작업이 실패한 시점을 알 수 있습니다.

beforeExecute가 활성 작업의 값을 증가시키고 afterExecute가 감소 시키도록 후크를 추가 할 수 있습니다. 물론 이러한 메서드는 각각의 필드에서 호출되므로 상호 잠금 개체에서 결과를 동기화해야합니다.

이러한 메서드를 사용하려면 선택한 ThreadPoolExecutor 개체를 재정의하고 거기에 후크를 추가하십시오.

예를 들어, 다음 코드는 희망 작동합니다 :

public class MyExecutor extends ThreadPoolExecutor { 
     //Lock object used for synchronization 
     private final Object lockObject = new Object(); 
     //Contains the active task count 
     private int activeTaskCount = 0; 
     //Failed task count 
     private int failedTaskCount = 0; 
     private int succeededTaskCount = 0; 

     public MyExecutor() { 
      //call super here with your parameters; 
     } 

     public int getActiveTaskCount(){ 
      synchronized(lockObject){ 
       return activeTaskCount; 
      } 
     } 

     public int getFailedTaskCount(){ 
      synchronized(lockObject){ 
       return failedTaskCount ; 
      } 
     } 

     public int getSucceededTaskCount(){ 
      synchronized(lockObject){ 
       return succeededTaskCount ; 
      } 
     } 

     protected void beforeExecute(Thread t, 
          Runnable r){ 
      super.beforeExecute(t,r); 
      synchronized(lockObject){ 
       activeTaskCount++; 
      } 
     } 

     protected void afterExecute(Runnable r,Throwable t){ 
      super.afterExecute(r,t); 
      synchronized(lockObject){ 
       activeTaskCount--; 
       if(t!=null){ 
        failedTaskCount++; 
       }else{ 
        succeededTaskCount++; 
       } 
      } 
     } 

} 
+1

이것은 불필요한 것으로 보입니다. ThreadPoolExecutor는 이미 [getActiveCount()] (http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#getActiveCount())를 제공합니다. –

+0

이 메소드가 제공 할 수는 있지만 실패한 계수는 아닙니다. afterExecute 메소드의 주석을 점검하십시오. 심지어 실행중인 runnables를 모두 한 세트로 유지한다면 runnables가 실행 중인지 확인할 수 있습니다. 이 방법은 간단한 샘플에 게시 한 것보다 더 많은 가능성을 허용합니다. – Tovi7

+0

나는 거기에 당신의 코멘트를 그리워했다; 예를 들어 실제 카운트가 아닌 예제로 실패한 카운트를 실제로 보여주는 것이 더 좋습니다. 또한,'t == null' 체크는 실행 (비즈니스 로직 "실패"가 아닌)에서 던져지는 * 심각한 * 에러 (체크되지 않은, 즉'RuntimeException','Error's)만을 체크합니다. "실패"와 "성공"의 개념은 API를 사용하는 개발자 만이 할 수 있습니다 (실행중인 스레드에서 RuntimeException을 던지는 대신'Future'를 사용하여 수행해야합니다). –

관련 문제