2010-03-01 3 views
6
import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 

class Task implements Callable<String> { 
    public String call() throws Exception { 
     String s = "initial"; 
     try { 
      System.out.println("Started.."); 
      /*for (int i=0;i<10000;i++) { 
       if (i % 2 == 0) { 
        System.out.println("Even"); 
       } 
      }*/ 
      boolean flag = true; 
      while(flag) { 

      } 
      System.out.println("Finished!"); 
      s = "Done"; 
     } 
     catch (RuntimeException e) { 
      s = "RuntimeException"; 
     } 
     catch (Exception e) { 
      s = "Exception"; 
     } 
     finally { 

     } 
     return s; 
    } 
} 

public class ExecutorServiceTest { 

    public static void main(String[] args) throws Exception { 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 5, TimeUnit.SECONDS); 
     executor.shutdown(); 
     Iterator<Future<String>> iter = result.iterator(); 
     while (iter.hasNext()) { 
      System.out.println("Came here"); 
      Future<String> fut = iter.next(); 
      System.out.println(fut.get()); 
     } 
    } 
} 

Есть ли способ, которым я могу остановить поток, выполняющий бесконечный цикл?Остановить бесконечный цикл в задании ExecutorService

ответ

7

Да, вы можете заменить flag (или логически &&) на !Thread.currentThread().isInterrupted().

Таким образом, когда задача canceled,, цикл будет завершен.

петля будет выглядеть примерно так:

while(!Thread.currentThread().isInterrupted() && flag) { 
    /* Do work. */ 
} 

Использование должно быть что-то вроде этого:

ExecutorService executor = Executors.newSingleThreadExecutor(); 
Future<String> task = executor.submit(new Task()); 
String str; 
try { 
    str = task.get(5, TimeUnit.SECONDS); 
} finally { 
    task.cancel(true); 
} 
0

Подумайте об использовании synchronized (this) { this.wait() } вместо sleep внутри call(), а затем, когда вы установите булево flag извне (возможно, напрямую или через метод flag(); с прямым доступом убедитесь, что переменная вашего флага равна volatile) call task.notifyAll(), чтобы разбудить спящий поток (убедитесь, что ваш объект задачи является локальной переменной, а не анонимным, чтобы вы могли вызывать методы на нем, и сделать флаг атрибутом класса в пределах Task).

Это также будет более эффективным, потому что цикл циклов ненужных циклов - точный механизм называется «защищенным блоком» (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html). Когда вы просыпаетесь из ожидания, проверьте переменную флага, чтобы убедиться, что она установлена.

Редактировать: посмотрел на оригинальный вопрос более подробно и создал пример с использованием существующего кода и принципов (есть более чем один способ скинуть кошку :)). Попробуйте это - петля здесь выходит из-за прерванного состояния текущей нити, которая была отменена из-за таймаута:

package ett; 
import java.util.Arrays; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.CancellationException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 

class Task implements Callable<String> { 
    public String call() throws Exception { 
     String s = "initial"; 
     System.out.println("Started.."); 
     for (int i=0;;i++) { 
      if (i % 2 == 0) { 
       System.out.println("Even"); 
      } 
      Thread.yield(); 
      if (Thread.interrupted()) break; 
     } 
     System.out.println("Finished!"); 
     s = "Done"; 

     return s; 
    } 
} 

public class ExecutorServiceTest { 

    public static void main(String[] args) throws Exception { 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 1, TimeUnit.SECONDS); 
     executor.shutdown(); 

     System.out.println("came here"); 

     for (Future<String> f : result) { 
      try { 
       System.out.println(f.get()); 
      } catch (CancellationException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
Смежные вопросы