Espere a que la tarea termine antes de terminar en ScheduledThreadPoolExecutor

Tengo un Runnable implementación que hace un trabajo que puede llevar algún tiempo y estoy tratando de programarlo usando ScheduledThreadPoolExecutorcon scheduleAtFixedRate método. Ahora quiero asegurarme de que el apagado sea correcto, es decir, antes de terminar, la tarea debe poder ejecutarse por completo. He escrito el siguiente código para el apagado.

 public void shutDown() throws Exception {
    try {
        LOG.info("Gracefully shutting down executor");
        executor.shutdown();
        if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
            // cancels currently executing tasks.
            LOG.info("Executor is still alive. Forcing executor thread pool to shut down");
            executor.shutdownNow();

            // Wait a while for tasks to respond to being cancelled
            if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
                LOG.fatal("Executor thread pool did not terminate");
                throw new Exception("Unable to shut down executor thread pool forcefully");
            }
            LOG.info("Executor shut down.");
        }
    } catch (Exception e) {
        LOG.error("Exception shutting down executor", e);
        throw e;
    }
}

Pero el problema con esto es que tengo que especificar el tiempo de espera explícitamente y no puedo predecir el tiempo que tomará la tarea de antemano. ¿Hay alguna manera de hacer que el ejecutor espere indefinidamente hasta que finalice la ejecución de la tarea sin tener que mencionar el tiempo de espera? ¿O hay una mejor manera de trabajar en el escenario anterior?

Muchas Gracias

Jitendra

preguntado el 01 de febrero de 12 a las 22:02

shutdown () debería hacer una terminación elegante, ¿verdad? según la documentación, shutdown () Inicia un apagado ordenado en el que se ejecutan las tareas enviadas anteriormente, pero no se aceptarán nuevas tareas. Cualquier motivo por el que tenga otro código relacionado con awaitTermination (...); ¿Desea forzar el apagado, si no se completa en cierto intervalo? -

Creo que solo inicia el apagado y sale, no bloquea ni espera hasta que se cierren los subprocesos. -

Quiero algún tipo de llamada de bloqueo para saber exactamente cuándo terminaron las tareas.

Puede utilizar un período de tiempo de espera ENORME, como 10000 HORAS. No creo que tus tareas necesiten mucho para terminar. :) -

sí, puedo ... pero pensé, debería haber una buena manera de hacer esto :) -

3 Respuestas

La solución más sencilla es "aprovisionar en exceso", por así decirlo. Le sugiero que use un período de tiempo de espera enorme que de ninguna manera puede excederse por el tiempo necesario para que se ejecute una sola tarea, como:

// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

Respondido 02 Feb 12, 03:02

Utilizan shutdown() para comenzar una terminación elegante y luego usar awaitTermination(long, TimeUnit) para esperar a que el servicio ejecutor termine de cerrarse.

Respondido 02 Feb 12, 02:02

Como se señaló en el comentario executor.shutdown() no obliga a salir de ninguna tarea, sino que evita que se acepten otras nuevas. Eche un vistazo en el javadoc.

Otro consejo es que si desea controlar sus tareas tan pronto como se completen, puede implementar Callable<T> en lugar de un Runnable que es de un tipo genérico y devuelve un valor de tipo T.Entonces puede ajustar esto Callable<T> en un FutureTask<V> y envíalo a tu ScheduledThreadPoolExecutor. Luego, puede recorrer sus tareas tan pronto como hayan completado su trabajo y estén disponibles. Entonces, en resumen, algo como esto (observe que tan pronto como terminemos de cargar el programador con tareas, es seguro cerrarlo, lo que significa que no permitimos que se envíen más tareas a partir de ese momento):

ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(n);
Callable<Integer> myTask = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myTask);
schedulerExecutor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
schedulerExecutor.shutdown();

Respondido 02 Feb 12, 03:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.