2014-12-02 3 views
0

그래서 호출 가능한 작업 중 일부는 invokeAll을 사용하여 ExecutorService에 제출하는의 중단에 민감한 입니다. 다른 메소드에서 5 초가 지난 후 executorService.shutdownNow를 호출 한 후 true를 반환하는 awaitTermination을 호출하므로 모두 양호한 것처럼 보입니다. 문제는 집행자가 종료되지 않는다는 것입니다.ExecutorService.invokeAll 및 종료

로깅으로 인해 각 작업이 완료되었다는 것을 알고 있습니다. 그럼에도 f.get 아직도 블록 내가 실행 프로그램 스레드들의 수와 동일하다 invokeAll을 :

다음 코드 AbstractExecutorService + 일부 로깅로부터 얻어진다.

 @Override 
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { 
     if (tasks == null) throw new NullPointerException(); 
     ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); 
     boolean done = false; 
     try { 
      List<Callable<T>> list = new ArrayList<Callable<T>>(); 
      for (Callable<T> t : tasks) { 
       list.add(t); 
       RunnableFuture<T> f = newTaskFor(t); 
       futures.add(f); 
       execute(f); 
      } 
      for (int i = 0, size = futures.size(); i < size; i++) { 
       Future<T> f = futures.get(i); 
       if (!f.isDone()) { 
        log.info("Future %s is not done!. Task %s", i, list.get(i)); 
        try { 
         log.info("Get from future %s", i); 
         // NEXT LINE BLOCKS FOR i= NUMBER OF THREADS 
         f.get(); 
         log.info("Got result from future %s", i); 
        } catch (CancellationException ignore) { 
        } catch (ExecutionException ignore) { 
        } 
       } 
      } 
      log.info("Obtained all!"); 
      done = true; 
      return futures; 
     } finally { 
      if (!done) for (int i = 0, size = futures.size(); i < size; i++) 
       futures.get(i).cancel(true); 
     } 
    } 

종료와 함께 invokeAll을 사용하지 않겠습니까? 나는 그들이 같은 수업을 듣고있는 것 같아. 왜 i가 executor의 스레드의 수인 경우에만 차단됩니까?

답변

1

그렇습니다. invokeAll을 종료과 함께 사용하면 안됩니다. 적어도 이것은 내가 이해하는 바이며 내가 잘못하면 나를 바로 잡습니다.

  • shutdownNow의 방법 : 유일한 것은이하는 것입니다
public List<Runnable> shutdownNow() { 
... 
     checkShutdownAccess(); 
     advanceRunState(STOP); 
     interruptWorkers(); 
     tasks = drainQueue(); 
... 
} 

작업 스레드를 인터럽트하고 작업 대기열에서보다 Runnable의 나머지 부분을 제거, drainQueue를 참조하십시오. 우리 invokeAll을 방법에 선물을 수정하지 않습니다 shutdownNow의/종료는 내 경우에 발생 그래서

N 스레드와 Executor에, 나는 5 초 후, 그들 각각 1 분 이상을, 300 개 일자리를 호출하는 것입니다 취소 (작업 스레드 인터럽트), N 개의 스레드가 중단되었습니다 (0에서 N-1). 나머지 선물은 어떻게 될까요? Nothing, f.get()에 대한 다음 호출 (질문에서 해당 줄 참조)이 차단되어 거기에 갇혀 있습니다. 이것은 내가 항상 i = 스레드 수에서 차단되는 이유를 설명합니다.