temporizador - java timer cancel
Java-El temporizador no se elimina después de la ejecución (3)
Tengo una aplicación que inicia un temporizador para salpicar un mensaje sobre las acciones del usuario. En el generador de perfiles JDK parece que todos los otros hilos se eliminan después de la ejecución por GC (supongo) pero los temporizadores creados no se eliminan. ¿Qué podría estar pasando allí?
mi cronómetro:
/**
* @param owner
* @param added
*/
public static void splashParentWithAnimation(AnchorPane owner, Parent added,double posX,double posY) {
// addParentWithAnimation(owner, added);
owner.getChildren().add(added);
AnchorPane.setLeftAnchor(added, posX);
AnchorPane.setTopAnchor(added, posY);
FadeTransition ft1 = new FadeTransition(Duration.millis(300), added);
ft1.setFromValue(0.0);
ft1.setToValue(1.0);
ft1.play();
Timer messagePrinter = new Timer();
messagePrinter.schedule(new TimerTask() {
@Override
public void run() {
Platform.runLater(() -> {
if (!owner.getChildren().contains(added))
return;
FadeTransition ft1 = new FadeTransition(Duration.millis(300), added);
ft1.setFromValue(1.0);
ft1.setToValue(0.0);
ft1.play();
ft1.setOnFinished((e) -> {
if (owner.getChildren().contains(added))
owner.getChildren().remove(added);
});
});
}
}, 1000);
}
¿Es porque estoy usando un método estático o debería destruirlo yo mismo?
Es porque necesita disponer el temporizador manualmente.
Si usa java.util.Timer
, necesita llamar al método cancel
para liberar recursos.
En realidad, no tienes ningún problema con la terminación del temporizador aquí. Los hilos que ve en el generador de perfiles ya están finalizados; tienen un cuadro blanco en el lado izquierdo que indica que están muertos.
El generador de perfiles muestra todos los hilos que se crearon durante la ejecución del programa, incluso si esos hilos ya están muertos y recogidos.
Puede confirmarlo fácilmente haciendo lo siguiente: en lugar de una lambda, cree una subclase de TimerTask
que haga lo mismo y redefina su método finalize()
para imprimir algo. Verá que cuando se realizan recolecciones de basura, sus tareas se finalizan. Solo puede suceder si los subprocesos se detienen, porque es el único lugar en la clase Thread
donde se Runnable
la referencia a Runnable
(que TimerTask
implementa).
Otra forma de confirmar esto es simplemente seleccionar ''Live Threads'' en la lista desplegable Ver en la parte superior de la tabla.
Además, te recomendaría sustituir el Timer
por algo mejor. Es demasiado derrochador crear un hilo cada vez que necesita retrasar alguna tarea. Echa un vistazo a ScheduledThreadPoolExecutor
, parece mucho más apropiado para tu tarea:
// Create a shared executor with a single thread
private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
// Instead of creating a Timer, schedule the task
executor.schedule(() -> {
// Do what you need here
}, 1, TimeUnit.SECONDS);
// Don''t forget to terminate the scheduler when you don''t need it anymore
scheduler.terminate();
Puede agregar más de un hilo al ejecutor si tiene demasiadas tareas programadas a la vez y esas tareas no son lo suficientemente pequeñas.
Su temporizador se crea con un hilo que no es daemon, hilos no daemon pueden bloquear la terminación de su programa. Deberías usar el constructor para el temporizador que lo hace usando un hilo daemon.
boolean daemon=true; Timer messagePrinter = new Timer(daemon);
Pero estaría usando un ExecutorService como sugiere Andrew Lygin .