2014-01-20 9 views
0

Я использую ThreadPoolExecutor для запуска потоков.Java - Получить состояние нити

ExecutorService executorService = Executors.newCachedThreadPool(); 
Future<?> future = executorService.submit(new MyRunnable()); 

Основываясь на некоторых условиях, мне нужно закончить длинную текущую нить и начать тот же экземпляр нити снова (для некоторых операций по очистке).

Поскольку у меня есть будущий объект потока, я могу легко проверить, работает ли он еще.

future.isDone() 

Если он работает, я могу послать сигнал прерывания с помощью

future.cancel(true); 

В MyRunnable классе, сигнал прерывания обрабатывается. Но это условие проверяется в начале цикла.

Проблема future.isDone() возвращает true, как только сигнал прерывания отправляется. Но мне нужно подождать, пока экземпляр потока действительно будет завершен.

Есть ли способ проверить, действительно ли поток работает/завершен?

+0

Если вы звоните 'future.cancel (истина) 'поток остановится, чтобы он не завершился. –

+0

Что вы подразумеваете под «* дождитесь завершения экземпляра потока. *"? Нитки в пуле потоков перерабатываются, поэтому, если есть неперехваченное исключение, сам поток не будет завершен ... – assylias

ответ

1

Apidoc также упоминает, что future.isDone() возвращает истину, если future.cancel() был вызван, то он не всегда скажет вам, если задача завершена. Чтобы проверить, завершена ли задача, вам необходимо получить доступ к Runnable, а затем вы можете проверить, завершена ли задача или дождаться ее завершения.
Сравните код ниже с выходом, показанным ниже, я думаю, что даст вам представление о ваших вариантах:

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class Q21227864 { 

public static void main(String[] args) { 

    ExecutorService executorService = Executors.newCachedThreadPool(); 
    Future<?> future = executorService.submit(new MyRunnable()); 
    sleep(100L); 
    future.cancel(true); 
    System.out.println("Future done: " + future.isDone()); 
    sleep(100L); 
    future.cancel(true); 
    System.out.println("Future done: " + future.isDone()); 
    sleep(500L); 
    System.out.println("Future done: " + future.isDone()); 

    System.out.println("---"); 

    MyRunnable mr = new MyRunnable(); 
    future = executorService.submit(mr); 
    sleep(100L); 
    future.cancel(true); 
    System.out.println("Runnable done: " + mr.isDone()); 
    sleep(100L); 
    System.out.println("Runnable done: " + mr.isDone()); 
    mr.waitForCleanup(); 
    System.out.println("Runnable done: " + mr.isDone()); 

    executorService.shutdownNow(); 
} 

public static void sleep(long timeMs) { 
    try { Thread.sleep(timeMs); } catch (Exception ignored) {} 
} 

static class MyRunnable implements Runnable { 

    final CountDownLatch completed = new CountDownLatch(1); 

    public void run() { 

     try { 
      System.out.println("Sleeping loop"); 
      Thread.sleep(1000L); 
      System.out.println("Sleeping loop done"); 
     } catch (Exception e) { 
      System.out.println("Stopped loop: " + e); 
     } 
     try { 
      System.out.println("Sleeping cleanup"); 
      Thread.sleep(300L); 
      System.out.println("Sleeping cleanup done"); 
     } catch (Exception e) { 
      System.out.println("Stopped cleanup: " + e); 
     } 
     completed.countDown(); 
    } 

    public boolean isDone() { 
     return (completed.getCount() == 0); 
    } 

    public void waitForCleanup() { 
     try { completed.await(); } catch (Exception ignored) {} 
    } 

} 

} 

Выход:

 
Sleeping loop 
Future done: true 
Stopped loop: java.lang.InterruptedException: sleep interrupted 
Sleeping cleanup 
Future done: true 
Sleeping cleanup done 
Future done: true 
--- 
Sleeping loop 
Runnable done: false 
Stopped loop: java.lang.InterruptedException: sleep interrupted 
Sleeping cleanup 
Runnable done: false 
Sleeping cleanup done 
Runnable done: true 
0

Я не думаю, что future.isDone() возвращает true, как только сигнал прерывания отправляется. Все задачи ThreadPoolExecutor выполняются с помощью FutureTask.run() метод

public class FutureTask<V> implements RunnableFuture<V> { 
    ...  
    public boolean isDone() { 
     return state != NEW; 
    } 

    public void run() { 
    ... 
      try { 
       Callable<V> c = callable; 
       if (c != null && state == NEW) { 
        V result; 
        boolean ran; 
        try { 
         result = c.call(); <-- this invokes your code 
         ran = true; 
        } catch (Throwable ex) { 
         result = null;  <-- if you threw InterruptedException 
         ran = false; 
         setException(ex); <-- state changes here 
        } 
        if (ran) 
         set(result);   <-- if your code simply returns then state changes here 
       } 
    ... 
Смежные вопросы