HOWTO · Kotlin

Cómo suspender la ejecución de un subproceso con Sleep en Kotlin

Aprende a pausar hilos de Kotlin/JVM con Thread.sleep o TimeUnit y cuándo usar delay o ScheduledExecutorService.

En esta página

Usa Thread.sleep cuando el código síncrono de Kotlin/JVM deba pausar el hilo actual. Usa TimeUnit.sleep cuando una unidad de tiempo con nombre haga más clara la espera. En las corrutinas, usa delay para suspender la corrutina sin bloquear su hilo; si una tarea debe ejecutarse más tarde, usa ScheduledExecutorService. Todo hilo dormido puede ser interrumpido, y una espera es un tiempo mínimo, no un instante exacto de ejecución.

Una corrutina es una unidad de ejecución no bloqueante; coroutine es el término técnico en inglés.

Bloquear el hilo actual con Thread.sleep

Thread.sleep(milliseconds) es la operación directa de la JVM para pausar el hilo que la llama. El argumento es un número Long de milisegundos y el método lanza InterruptedException. El código de producción debe restaurar la marca de interrupción o propagarla, en vez de imprimir silenciosamente una traza.

fun main() {
    println("before")
    try {
        Thread.sleep(100L)
        println("after")
    } catch (exception: InterruptedException) {
        Thread.currentThread().interrupt()
        println("interrupted")
    }
}

Salida:

before
after

Usar la función Sleep de Kotlin desde Thread

Esto bloquea el hilo que llama durante al menos aproximadamente 100 milisegundos. No detiene toda la JVM: otros hilos listos pueden continuar. Evítalo en un bucle de eventos o en un hilo de trabajo limitado si el trabajo puede expresarse como una suspensión no bloqueante.

Usar unidades legibles con TimeUnit.sleep

TimeUnit, de java.util.concurrent, convierte una unidad con nombre, como segundos o milisegundos, antes de dormir. Sigue bloqueando el hilo actual y respondiendo a interrupciones, pero TimeUnit.SECONDS.sleep(1) es más fácil de revisar que una conversión literal de milisegundos.

import java.util.concurrent.TimeUnit

fun main() {
    println("before")
    try {
        TimeUnit.MILLISECONDS.sleep(100)
        println("after")
    } catch (exception: InterruptedException) {
        Thread.currentThread().interrupt()
        println("interrupted")
    }
}

Salida:

before
after

Usar la función Sleep de Kotlin desde TimeUnit

Elige la unidad que corresponda al requisito. La conversión no garantiza un tiempo exacto: la planificación, la contención o la resolución del temporizador del sistema operativo pueden hacer que el hilo continúe más tarde.

Usar delay dentro de una corrutina

delay es una función suspendida de kotlinx-coroutines-core. Pausa la corrutina sin bloquear el hilo subyacente, de modo que otra corrutina pueda usarlo. Debe llamarse desde una función suspendida o un ámbito de corrutina; no sustituye a Thread.sleep en código síncrono ordinario.

Usar la función delay de Kotlin

Por ejemplo, un ámbito runBlocking puede iniciar una corrutina que llame a delay(100L) y después imprima un mensaje. El orden depende de la planificación; la cancelación también es un límite importante: delay admite cancelación, por lo que una corrutina cancelada normalmente se detiene en el punto de suspensión. Añade kotlinx-coroutines-core antes de compilar código de corrutinas; la biblioteca estándar de Kotlin no proporciona delay por sí sola.

Programar trabajo con ScheduledExecutorService

Usa ScheduledExecutorService cuando el requisito sea «ejecutar esta tarea más tarde» y no «hacer dormir este hilo». Una tarea programada puede cancelarse antes de ejecutarse, y el executor debe cerrarse cuando ya no sea necesario.

import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

fun main() {
    val executor = Executors.newSingleThreadScheduledExecutor()
    val task = executor.schedule(
        { println("task ran") },
        100,
        TimeUnit.MILLISECONDS,
    )

    task.get()
    executor.shutdown()
}

Salida:

task ran

Aquí get() solo mantiene vivo el ejemplo corto de línea de comandos hasta que termina la tarea. En una aplicación, conserva el ScheduledFuture devuelto si necesitas cancelarla y usa shutdown o shutdownNow según el ciclo de vida de la aplicación. La planificación no es una garantía de tiempo real preciso.

¿Qué método de Sleep de Kotlin debes elegir?

  • Usa Thread.sleep para una operación JVM síncrona pequeña en la que bloquear el hilo actual sea intencional.
  • Usa TimeUnit.sleep para el mismo comportamiento bloqueante con una unidad legible.
  • Usa delay en corrutinas para una suspensión cancelable y no bloqueante.
  • Usa ScheduledExecutorService cuando deba activarse una tarea separada después de una espera.

No uses wait() como operación general de Sleep. Object.wait() de Java participa en la coordinación de monitores y requiere el monitor apropiado; resuelve otro problema de sincronización. Con cualquier API, trata la interrupción y la cancelación como resultados normales del flujo de control, no como errores inesperados.