Estoy tratando de asegurarme de que mi aplicación Java toma medidas razonables para ser robusto, y a parte de que implica apagar correctamente. Estoy leyendo sobre ganchos de cierre y yo en realidad no entiendo cómo hacer uso de ellos en la práctica.

Hay un ejemplo práctico que existe?

Digamos que he tenido una aplicación muy simple como este de abajo, que escribe números en un archivo, de 10 a una línea, en lotes de 100, y quiero asegurarme de que un determinado lote termina si el programa se interrumpe. Cómo puedo obtener el registro de un cierre de gancho pero no tengo idea de cómo integrar eso en mi aplicación. Alguna sugerencia?

package com.example.test.concurrency;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class GracefulShutdownTest1 {
final private int N;
final private File f;
public GracefulShutdownTest1(File f, int N) { this.f=f; this.N = N; }
public void run()
{
PrintWriter pw = null;
try {
FileOutputStream fos = new FileOutputStream(this.f);
pw = new PrintWriter(fos);
for (int i = 0; i < N; ++i)
writeBatch(pw, i);
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
finally
{
pw.close();
}       
}
private void writeBatch(PrintWriter pw, int i) {
for (int j = 0; j < 100; ++j)
{
int k = i*100+j;
pw.write(Integer.toString(k));
if ((j+1)%10 == 0)
pw.write('\n');
else
pw.write(' ');
}
}
static public void main(String[] args)
{
if (args.length < 2)
{
System.out.println("args = [file] [N] "
+"where file = output filename, N=batch count");
}
else
{
new GracefulShutdownTest1(
new File(args[0]), 
Integer.parseInt(args[1])
).run();
}
}
}
InformationsquelleAutor Jason S | 2010-05-27

2 Comentarios

  1. 152

    Se podría hacer lo siguiente:

    • Dejar el enlace de cierre de establecer algunas AtomicBoolean (o volátiles boolean) «keepRunning» a false
    • (Opcionalmente, .interrupt el trabajo hilos si se espere de datos en algunos de bloqueo de llamadas)
    • Esperar para los subprocesos de trabajo (ejecución de writeBatch en su caso) para terminar, llamando a la Thread.join() método en el trabajo hilos.
    • Terminar el programa

    Algunos de boceto código:

    • Agregar un static volatile boolean keepRunning = true;
    • En run() de cambiar a

      for (int i = 0; i < N && keepRunning; ++i)
      writeBatch(pw, i);
    • En main() agregar:

      final Thread mainThread = Thread.currentThread();
      Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
      keepRunning = false;
      mainThread.join();
      }
      });

    Que es más o menos como puedo hacer un agraciado «rechazar todos los clientes al presionar Control-C» en la terminal.


    De el docs:

    Cuando la máquina virtual comienza su secuencia de cierre comenzará a todos los inscritos cierre de ganchos en algunos no especificado orden y dejar que ellos se ejecutan concurrentemente. Cuando todos los ganchos han terminado realizará todos los uninvoked finalizadores si la finalización-en-salida ha sido habilitado. Finalmente, la máquina virtual va a detener.

    Que es, un enlace de cierre mantiene la JVM ejecuta hasta que el gancho se ha terminado (regresó de la run()-método.

    • Ah, así, si yo entiendo a la derecha, la esencia de lo que estás diciendo es que el cierre de gancho tiene una oportunidad de comunicarse con otros actualmente en ejecución hilos, y para mantener fuera de la de VM de cierre (por ejemplo, mediante el uso de Hilo.join()) hasta que esté satisfecho de que una rápida limpieza se ha completado. Ese es el punto que me faltaba. gracias!
    • Sí. Usted lo consiguió. Actualizada la respuesta con un par de frases a partir de la documentación.
    • Lo siento de antemano,pero no GracefulShutdownTest1 implementar Runnable?
    • ¿Esto también funciona una interfaz gráfica de usuario que se inició en el hilo principal? Sé que no es la mejor manera de hacerlo (uso de la EDT en su lugar), pero estoy trabajando en el viejo código.
    • Cierre de ganchos no están relacionados con el código GUI. Los dos deben trabajar juntos muy bien.
    • ¿Hay limitaciones a la duración de la parada de gancho se puede ejecutar? Por ejemplo, puede «prevenir» la máquina virtual de dejar de indefinidamente?
    • Creo que no hay ningún tipo de limitaciones. Usted puede evitar que la JVM cerrando por desove no demonio hilo así.
    • Así que si este ejemplo había estado usando múltiples hilos, su join() llamada se efectúa en el hilo hacer el trabajo?
    • Whati es el mainThread.join() de llamadas para?
    • la JVM se termina cuando todos los no-demonio de hilos que han terminado. Si el mainThread es un demonio subproceso, el join garantiza que esperar a que termine antes de dejar que la JVM apagar.

Dejar respuesta

Please enter your comment!
Please enter your name here