Fundamentos de Hilos en Java

La concurrencia en Java se maneja principalmente a través de su API de Hilos (Threads), que permite la ejecución simultánea de múltiples tareas. Esto optimiza el uso de la CPU y mejora el rendimiento general de las aplicaciones.

Conceptos Clave

Procesos vs. Hilos

  • Proceso: Unidad de asignación de recursos del sistema operativo.
  • Hilo: Unidad de ejecución dentro de un proceso. Un proceso puede contener múltiples hilos.

Estados de un Hilo

Un hilo en Java puede encontrarse en varios estados durante su ciclo de vida:

  • NEW: El hilo ha sido creado pero aún no ha sido iniciado.
  • RUNNABLE: El hilo está listo para ejecutarse o está en ejecución.
  • BLOCKED: El hilo está esperando para adquirir un bloqueo de monitor (semaforo).
  • WAITING: El hilo está esperando indefinidamente la intervención de otro hilo.
  • TIMED_WAITING: El hilo está esperando por un período de tiempo específico.
  • TERMINATED: El hilo ha finalizado su ejecución.

Transiciones de Estado

Las transiciones entre los estados de un hilo son provocadas por diversas acciones:

Diagrama de estados de un hiloMétodos Comunes

1. Control de Ciclo de Vida

Método Clase/Interfaz Descripción Consideraciones
start() Thread Inicia la ejecución del hilo, pasándolo al estado RUNNABLE. Solo puede llamarse una vez. Una segunda llamada lanza IllegalThreadStateException.
run() Thread/Runnable Contiene el código que el hilo ejecutará. Llamar run() directamente no inicia un nuevo hilo; se ejecuta en el hilo actual.
sleep(long millis) Thread Pausa la ejecución del hilo actual durante el tiempo especificado. No libera los bloqueos (locks) que el hilo posea.
yield() Thread Sugiere al planificador que ceda el tiempo de CPU. Es solo una sugerencia; no hay garentía de que el hilo ceda el control.
interrupt() Thread Intenta interrumpir el hilo. Establece una bandera de interrupción. Debe ser manejado explícitamente por el hilo (usando isInterrupted()).
isInterrupted() Thread Verifica si el hilo ha sido interrumpido. No modifica el estado de interrupción.
interrupted() Thread Verifica y borra el estado de interrupción del hilo actual. Método estático; afecta al hilo que lo llama.

2. Métodos de Sincronización

Método Clase/Interfaz Descripción Consideraciones
wait() Object Libera el bloqueo del monitor y pone al hilo en estado WAITING. Debe ser invocado dentro de un bloque synchronized.
notify() Object Despierta a un hilo arbitrario que esté esperando en el monitor de este objeto. Debe ser invocado dentro de un bloque synchronized.
notifyAll() Object Despierta a todos los hilos que estén esperando en el monitor de este objeto. Debe ser invocado dentro de un bloque synchronized.
join() Thread Espera a que el hilo de destino termine su ejecución. Implementado internamente usando wait().
join(long millis) Thread Espera a que el hilo de destino termine o hasta que transcurra el tiempo especificado. Continúa la ejecución si el tiempo expira.

Formas de Crear Hilos

1. Extender la Clase Thread

Define una nueva clase que herede de Thread y sobrescribe el método run().


class MiHilo extends Thread {
    @Override
    public void run() {
        System.out.println("Hilo ejecutándose...");
    }
}

// Uso:
MiHilo hilo = new MiHilo();
hilo.start();

2. Implementar la Interfaz Runnable

Crea una clase que implemente Runnable y proporciona la lógica en el método run().


class MiRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Hilo ejecutándose...");
    }
}

// Uso:
Thread hilo = new Thread(new MiRunnable());
hilo.start();

3. Implementar la Interfaz Callable (Retorno de Valor)

Similar a Runnable, pero el método call() puede devolver un resultado y lanzar excepciones.


import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class MiCallable implements Callable<string> {
    @Override
    public String call() throws Exception {
        // Simula una tarea que devuelve un resultado
        return "Resultado de la tarea";
    }
}

// Uso con Thread:
FutureTask<string> futureTask = new FutureTask<>(new MiCallable());
Thread hilo = new Thread(futureTask);
hilo.start();
try {
    String resultado1 = futureTask.get(); // Espera y obtiene el resultado
    System.out.println("Resultado 1: " + resultado1);
} catch (Exception e) {
    e.printStackTrace();
}

// Uso con ExecutorService (Pool de Hilos):
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<string> future = executor.submit(new MiCallable());
try {
    String resultado2 = future.get(); // Espera y obtiene el resultado
    System.out.println("Resultado 2: " + resultado2);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    executor.shutdown(); // Cierra el pool de hilos
}
</string></string></string>

4. Pools de Hilos (Executor Framework)

Java proporciona el framework ExecutorService para gestionar pools de hilos de manera eficiente. Se discutirá más a fondo en secciones posteriores.


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

// Ejemplo de definición de tareas (se asume que existen RunnableTask y CallableTask)
// class RunnableTask implements Runnable { ... }
// class CallableTask implements Callable<string> { ... }

// Crear un pool de hilos con 10 hilos
ExecutorService executor = Executors.newFixedThreadPool(10);

// Enviar tareas para ejecución
// executor.execute(new RunnableTask());
// Future<string> future = executor.submit(new CallableTask());

// Al finalizar, cerrar el pool de hilos
// executor.shutdown();
</string></string>

Etiquetas: java hilos concurrencia multihilo thread

Publicado el 6-29 05:59