2010-03-01 29 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()); 
     } 
    } 
} 

¿Hay alguna manera de detener el hilo que ejecuta el bucle infinito?Detener un bucle infinito en una tarea ExecutorService

Respuesta

7

Sí, puede reemplazar flag (o lógicamente &&) con !Thread.currentThread().isInterrupted().

De esta manera, cuando la tarea es canceled,, el ciclo finalizará.

El bucle sería algo como esto:

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

uso debe ser algo como esto:

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

Piense en usar synchronized (this) { this.wait() } en lugar de sleep dentro call(), y luego cuando se establece el valor booleano flag externamente (quizás directamente o mediante un método flag(); con acceso directo asegúrese de que su variable de indicador sea volatile) llame al task.notifyAll() para activar el hilo que duerme (asegúrese de que su objeto de tarea sea una variable local en lugar de tenerlo anónimo para que pueda invocar métodos sobre él, y hacer que el marcador sea un atributo de clase dentro de Task).

También será más eficiente así porque los bucles desperdician ciclos innecesariamente; el mecanismo exacto se denomina 'bloque guardado' (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html). Cuando se despierte de la espera, pruebe la variable de indicador solo para asegurarse de que esté configurada.

Editar: examiné más de cerca la pregunta original y creé un ejemplo utilizando el código y los principios existentes (hay más de una manera de despellejar a un gato :)). Intente esto: el ciclo aquí sale debido al estado interrumpido del hilo actual, que se ha cancelado debido al tiempo de espera: