2009-07-24 2 views
6

Java에서 Futures 및 ScheduledExecutorService를 살펴보기 시작한 중입니다. Callable이 내가 지정한 일정에 따라 실행되지 않는 이유가 궁금합니다. 이 샘플 코드에서는 호출 가능 코드가 한 번 실행되지만 앱이 완료되지 않으며 작업이 다시 실행되지 않습니다. 이는 내가 예상했던 것입니다 (문제가 내 기대와 맞다고 확신합니다).Java에서 Clarity 탐색 ScheduledExecutorService 및 FutureTask

Runnables는 정상적으로 작동합니다. Callables는 영원히 막는 것처럼 보입니다. 그러나 나는 왜 ... 나는 무엇을 놓치고 있습니까?

감사합니다.

public class ExecutorExample { 

    /** 
    * @param args 
    * @throws ExecutionException 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException, ExecutionException { 

     ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); 

     FutureTask<ArrayList<String>> ft1 = new FutureTask<ArrayList<String>>(new Callable<ArrayList<String>>(){ 
      @Override 
      public ArrayList<String> call() { 
       ArrayList<String> stuff = new ArrayList<String>(); 
       for(int i = 0;i<10;i++){ 
        String thing ="Adding " + i + " to result"; 
        stuff.add(thing); 
        System.out.println(thing); 

       } 
       return stuff; 
      }}); 

     scheduler.scheduleAtFixedRate(ft1, 0, 1, TimeUnit.SECONDS); 

     System.out.println(ft1.get()); 
     System.out.println(ft1.isDone()); 

    } 
} 

답변

8

문제는 FutureTask 사용, 그 클래스에 대한 설명이 말한대로,이다 "계산이 완료되면, 계산이 다시 시작하거나 취소 할 수 없습니다." FutureTaskrun 방법은 한 번 호출 한 후

는, 이후의 호출은 작업의 Callable 인스턴스에 위임하지 않고 즉시 반환.

되풀이 작업으로 Runnable 만 사용할 수 있으며 결과를 되돌릴 수 없습니다. 대신 Runnable 작업에 run 메서드가 끝날 때 호출 할 수있는 콜백을주고 작업의 각 실행 결과를 다른 스레드의 수신기에보고합니다.

+1

나는 이것을 잘 모른다. FutureTask는 Runnable을 구현하며 call() 메서드를 호출하고 결과를 저장할 것으로 기대합니다. 그런 다음 작업이 완료 될 때까지 get()을 차단하거나 캐시 된 결과를 즉시 반환 할 것을 기대합니다. 그러면 스케줄러가 FutureTask를 실행하지 않아 call()이 발생하고 나중에 수집하기 위해 결과가 캐시됩니까? –

+1

네, 단 한 번입니다. 첫 번째 이후에 예정된 호출은 FutureTask에서'run'을 호출하지만 Callable에서'call'을 호출하지 않고 "short-circuits"메소드를 실행합니다. 그러나 스케줄러는이를 인식하지 못하고 FutureTask를 호출하기 위해 계속 실행하므로 프로그램이 종료되지 않습니다. – erickson

+0

완벽한 의미가 있습니다. 나는 Executors와 그 ilk를위한 javadocs에서 매우 머리가났다. 그리고 나는 FutureTask에서 그 명백한 라인을 완전히 놓쳤다. 후속 질문으로, 내 작업의 결과로 발생시키고 싶은 것이 BlockingQueue가 업데이트되면, 그 큐를 각 실행 가능 파일에 전달하거나 외부에서 살 수있는 리스너를 구현하는 것이 더 바람직할까요? 결과에 따라 큐를 조작하는 runnable? 다시 한 번 감사드립니다 –