Pregunta Latido del corazón en Java: timerTask o thread.sleep ()?


Quiero implementar un cliente muy simple al latido del servidor en java. El enfoque más simple parece ser a través del sueño. Considera el metacódigo abajo.

class MyClass

    Thread heartbeatThread = new Thread();

    public void() startHeartBeat{
         Thread.sleep(4000);
         sock.write("H");
      }

¿Es esta una solución adecuada o hay escollos que no estoy considerando?

También he considerado usar el java.util.Timer.scheduleAtFixedRate enfoque. ¿Sería esto más robusto / confiable? Si es así, ¿por qué? Aquí hay un ejemplo (no es tan limpio IMO):

class HeartBeat
{
    Timer timer=new Timer();

    public void scheduleHeartBeat(int delay, int period) {
       timer.scheduleAtFixedRate( new HeartBeatTask(), delay, period);     
       }
}   

class HeartBeatTaskextends TimerTask {
     public void run() {
     sock.write("H");     
}

¿Se otorgará mayor prioridad al segundo enfoque?


5
2018-03-09 14:29


origen


Respuestas:


En primer lugar, su Threadidioma basado en la base no se programará a velocidad fija sin un ciclo infinito.

Esa es una desventaja también: es probable que desee establecer alguna condición para salir del ciclo.

También necesitas atrapar InterruptedException cuando se invoca estática Thread.sleep.

Otro idioma popular para la ejecución programada es mediante el uso de un ScheduledExecutorService.


Encuentra las 3 alternativas a continuación:

Minutero

// says "foo" every half second
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        System.out.println("foo");
    }
}, 0, 500);
  • Pros: sencillo
  • Contras:

En la ejecución de tasa fija, cada ejecución se programa en relación con el tiempo de ejecución programado de la ejecución inicial. Si una ejecución se retrasa por algún motivo (como recolección de basura u otra actividad de fondo), dos o más ejecuciones ocurrirán en sucesión rápida para "ponerse al día".

Documentos aquí.


Bucle infinito

new Thread() {
    @Override
    public void run() {
        while (true) {
            // Says "blah" every half second
            System.out.println("blah");
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                // nope
            }
        }
    }
}.start();
  • Pros: super simple. Puede variar su retraso recurrente programáticamente.
  • Contras: Thread.sleep es todavía

sujeto a la precisión y precisión de los temporizadores y programadores del sistema.   ... y requiere captura InterruptedException.

Documentos aquí.

También:

  • su ciclo infinito podría requerir una condición de ruptura (de alguna manera potencialmente engorrosa)
  • sin configuración de retardo inicial a menos que se aplique manualmente antes del bucle infinito, lo que requeriría otro try / catch.

Ejecutores

ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor();
es.scheduleAtFixedRate(
    new Runnable() {
        @Override
        public void run() {
            // Says "bar" every half second
            System.out.println("bar");
        }
    }, 
    0, 500, TimeUnit.MILLISECONDS);
  • Pros: esta es la característica más reciente de 3. Muy simple y elegante, también puede programar Callables (no a tasa fija) y reutilizar el ExecutorService. La documentación para java.util.Timer en realidad menciona ScheduledThreadPoolExecutor (implementando el ScheduledExecutorService interfaz) como un "reemplazo más versátil para el Timer/TimerTask combinación".
  • Contras como documentado:

Si cualquier ejecución de esta tarea lleva más tiempo que su período, las ejecuciones posteriores pueden comenzar tarde,

Documentos aquí.


11
2018-03-09 14:44



Sí, no sé cómo se implementan los temporizadores internamente, pero lo que sí entiendo aquí es que, si usa el modo de suspensión, tendrá que manejar la excepción InterruptedException, y comer esa excepción puede no ser una buena práctica. además, las tareas del temporizador se ejecutarían dentro de su espacio de subprocesos, y usted tiene un mejor control sobre ellas.

Puede detener el cronómetro en cualquier momento si lo desea, en este caso, es posible que no pueda hacer eso


1
2018-03-09 14:43



Si usa el enfoque de suspensión, hay algunos problemas que debe considerar.

Una es que el tiempo de sueño no es exacto, y podrías haber ido a la deriva con el tiempo (tal vez mientras el hilo está durmiendo, otra aplicación acapara la CPU y el hilo tarda más de lo esperado en enviar su latido, ahora la próxima vez que se envíe el hilo un latido cardíaco se retrasa), su tiempo de sueño se verá incrementado gradualmente por varias cosas (no dormirá por menos de su tiempo de sueño, pero con frecuencia puede dormir un poco más), y esos incrementos se acumularán con el tiempo.

Otra es que podría tener un problema con el zócalo, tendría que escribir código para manejar la creación de una nueva conexión.

El subproceso debería ser de buen comportamiento y responder a una interrupción, o bien ser un subproceso de demonio. Si tuviera que compartir datos entre hilos, necesitaría conocer los problemas de visibilidad de la memoria.

Usar un temporizador significaría que cada lanzamiento de una tarea tendría un nuevo comienzo y usted no sería vulnerable a retrasos acumulados o conexiones de red obsoletas.


1
2018-03-09 14:37