Pregunta

En el código de abajo, estoy captura de un TimeoutException después de 100 segundos según lo previsto. En este punto, yo esperaría que el código para salir del principal y el programa de interrumpir pero mantiene la impresión de la consola. ¿Cómo consigo la tarea de detener la ejecución después del tiempo de espera?

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;
    }


}
¿Fue útil?

Solución

Se necesita cancelar su tarea en tiempo de espera (e interrumpir su rosca). Eso es lo que el método es para 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;
}

Otros consejos

Su necesidad rescatable para poder parar rápidamente, cuando sea necesario.

Su código:

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;
}

ya es capaz de hacer eso gracias a llamar Thread.sleep(). El punto es que futureTask.cancel(true) interrumpirá otro hilo, y su código necesita reaccionar a esta interrupción. Thread.sleep() hace eso. Si no ha utilizado Thread.sleep() u otro código de bloqueo interrumpible, que tendría que comprobar Thread.currentThread().isInterrupted() por sí mismo, y dejar de fumar tan pronto como sea posible (por ejemplo, lanzando new InterruptedException()) cuando se encuentra que esto es cierto.

Es necesario llamar futureTask.cancel(true); de su manejador de excepciones para cancelar e interrumpir hilo que ejecuta la tarea.

Mi consejo es aprender sobre mecanismo de interrupción (esto es gran artículo: Tratar con InterruptedException ), y utilizarlo.

Una vez que captó la TimeoutException, es necesario llamar al método cancel (verdadero) de su tarea ...

o apagar el ExecutorService llamando shutdownNow () ...

o salir de la máquina virtual llamando System.exit (0)

en función de sus necesidades

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top