2009-08-15 15 views
7

W poniższym kodzie przechwytywania TimeoutException po 100 sekund zgodnie z przeznaczeniem. W tym momencie oczekiwałbym, że kod wyjdzie z programu głównego i programu, ale zakończy drukowanie na konsoli. Jak sprawić, aby zadanie przestało działać po przekroczeniu limitu czasu?Jak ustawić funkcję FutureTask w celu powrotu po przekroczeniu limitu czasu?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); 

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 
    FutureTask<T> task = new FutureTask<T>(c); 
    THREAD_POOL.execute(task); 
    return task.get(timeout, timeUnit); 
} 


public static void main(String[] args) { 

    try { 
     int returnCode = timedCall(new Callable<Integer>() { 
      public Integer call() throws Exception { 
       for (int i=0; i < 1000000; i++) { 
        System.out.println(new java.util.Date()); 
        Thread.sleep(1000); 
       } 
       return 0; 
      } 
     }, 100, TimeUnit.SECONDS); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return; 
    } 


} 

Odpowiedz

8

trzeba anulować zadanie po przekroczeniu tego limitu (i przerwać wątek). Do tego służy metoda cancel(true). :

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); 

private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 
    THREAD_POOL.execute(task); 
    return task.get(timeout, timeUnit); 
} 


public static void main(String[] args) { 
     try { 
      FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() { 
       public Integer call() throws Exception { 
         for (int i=0; i < 1000000; i++) { 
           if (Thread.interrupted()) return 1; 
           System.out.println(new java.util.Date()); 
           Thread.sleep(1000); 
         } 
         return 0; 
       } 
      }); 
      int returnCode = timedCall(task, 100, TimeUnit.SECONDS); 
     } catch (Exception e) { 
       e.printStackTrace(); 
       task.cancel(true); 
     } 
     return; 
} 
+1

! Task.cancelled() powinno być! IsCancelled() jak djna pierwotnie napisał – Zed

+1

Myślę, że znacznie lepiej jest używać przerw. Po pierwsze, twój kod wywoływalny wcale nie musi wiedzieć o 'zadaniu'. Po drugie, jeśli używasz różnych operacji blokowania w swoim kodzie wywoływanym (jak 'Thread.sleep()'), nie będą one reagować na task.isCancelled(), ale zazwyczaj reagują na przerwy. Zatem używanie 'cancel (true)' i uświadamianie kodu o przerwach jest zwykle najlepszym sposobem na zrobienie tego. (Twój kod będzie również bardziej ogólny, ponieważ mechanizm przerw jest tak szeroko stosowany w Javie) –

+0

Chyba moim punktem jest to, że "Przerwanie jest mechanizmem współpracy". (http://www.ibm.com/developerworks/java/library/j-jtp05236.html) –

1

Po złapał TimeoutException, trzeba zadzwonić do odwołania (true) metodę swojego zadania ...

lub wyłączyć ExecutorService wywołując shutdownNow() ...

lub zamknąć VM poprzez wywołanie System.exit (0)

zależności od potrzeb

4

Twój Musi być w stanie zatrzymać się szybko, gdy jest to konieczne.

Kod:

public Integer call() throws Exception { 
    for (int i=0; i < 1000000 && !task.cancelled(); i++) { 
     System.out.println(new java.util.Date()); 
     Thread.sleep(1000); // throws InterruptedException when thread is interrupted 
    } 
    return 0; 
} 

jest już w stanie to zrobić dzięki nazywając Thread.sleep(). Chodzi o to, że futureTask.cancel(true) przerwie inny wątek, a twój kod musi zareagować na tę przerwę. Thread.sleep() to robi. Jeśli nie używałeś Thread.sleep() lub innego przerywalnego kodu blokującego, musisz samodzielnie sprawdzić numer Thread.currentThread().isInterrupted() i zamknąć go jak najszybciej (np. Rzucając new InterruptedException()), gdy uznasz, że jest to prawdą.

Musisz zadzwonić pod numer futureTask.cancel(true); z programu obsługi wyjątków, aby anulować i przerwać wątek, który uruchamia zadanie.

Moja rada to zapoznać się z mechanizmem przerwania (jest to świetny artykuł: Dealing with InterruptedException) i używać go.