¿Cómo demorar la ejecución de un método en Java 1/2?

Cuando iniciamos en cualquier lenguaje de programación por alguna u otra razón siempre necesitamos encontrar una forma de poder “dormir” la ejecución de nuestra aplicación por unos instantes; por lo general lo hacemos con fines para pruebas pero a efectos prácticos puede ser útil en muchos escenarios. Siempre; cuando necesitamos esto vamos a Google y ponemos “sleep en Java” o “sleep en el lenguaje X“. En la entrada actual veremos 2 formas para demorar la ejecución de un método en Java, iremos un poco más allá del simple sleep.

Thread.sleep

La solución más conocida es sin dudas Thread.sleep(long millis). Esta solución, es sin dudas funcional, pero tiene el inconvenientes de que actúa sobre el thread actual de ejecución, y capaz no sea óptima para todos los escenarios.

Ejemplo en código:

  try {
            Thread.sleep(time);
            mimetodo();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("Thread was interrupted");
        }

En el ejemplo anterior se espera “time” en milisegundos y luego se ejecuta mimetodo(), esta forma tiene varios inconvenientes:

  • El curso de ejecución se detiene completamente durante “time” milisegundos, por lo que el Thread queda detenido por ese tiempo.
  • El hilo en curso puede ser detenido por otro, lanzándose la excepción y nunca llegando a ejecutarse mimetodo().
  • Es totalmente bloqueante al flujo.

Este último punto es especialmente importante, porque si bien es cierto que mimetodo() no se ejecutará hasta que no pase el tiempo definido tampoco se ejecutará ninguna otra lógica en ese hilo. Este escenario no siempre es requerido. En ocasiones queremos que mimetodo() se ejecute al cabo de x time, pero deseamos que el flujo siga y cuando pase ese tiempo entonces se llame de forma asíncrona a mimetodo().

Si definitivamente, queremos usar Thread.sleep, entonces les recomiendo como una buena práctica externalizarlo en una clase aparte para poder reusarlo cuando sea necesario, veamos el siguiente ejemplo:

public class SleeperBasic {
    // Stop current thread "time", and after run
    public void runWithDelay(Runnable runnable,  long time) {
        try {
            Thread.sleep(time);
            runnable.run();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("Thread was interrupted");
        }
    }
}

Como vemos, se pasa una instancia de tipo Runnable, la cual invocamos luego del sleep, el time del método estaría expresando en milisegundos. Veamos un ejemplo de llamada.

public class ThreadSleepBasic {
    private static SleeperBasic sleeperBasic;
    public ThreadSleepBasic() {
        sleeperBasic = new SleeperBasic();
    }
    public void doTaskX(){
        System.out.println("Doing task X");
    }
    public static void main(String[] args) {
      long time = 2000;
      ThreadSleepBasic threadSleepBasic = new ThreadSleepBasic();
      System.out.println("Step 1");
      sleeperBasic.runWithDelay(()->threadSleepBasic.doTaskX(), time);
      Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getId() + "- " + t.getName()));
      System.out.println("Step 2");
    }
}

Pongamos el foco en el método main, específicamente en:

sleeperBasic.runWithDelay(()->threadSleepBasic.doTaskX(), time);

Como vemos en el primer parámetro de esta función le pasamos nuestro Runnable, que es el método que queremos ejecutar como una expresión lambda, en el segundo parámetro el tiempo de demora.

No hacerle mucho caso a la línea:

      Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getId() + "- " + t.getName()));

Su función acá ese solo para debug, nos permitirá mostrar los threads activos.

Puedes ver todo el código en GitHub, el cual puedes probar.

1 thought on “¿Cómo demorar la ejecución de un método en Java 1/2?

Comments are closed.