1. Paso de parámetros a los hilos
Cuando lanzas un hilo, a menudo quieres pasarle algún «trabajo»: un nombre de archivo, un rango de números o un saludo. Un hilo sin parámetros es como un mensajero sin dirección: corre por la ciudad, pero no sabe a dónde entregar la pizza.
¿Cómo se hace?
En Java, los hilos suelen crearse de dos maneras:
- Herencia de la clase Thread
- Implementación de la interfaz Runnable (o uso de expresiones lambda)
El paso de parámetros se hace con más frecuencia a través del constructor de la clase que implementa Runnable. Es simple, seguro y claro. Declara los campos como final y protegerás los parámetros de modificaciones desde otros hilos. Usar setters/campos públicos puede acarrear problemas de sincronización.
Ejemplo 1: Hilo con parámetro a través del constructor
Mejoraremos una aplicación didáctica: procesar los pedidos de los usuarios en un hilo aparte.
public class OrderProcessor implements Runnable {
private final String orderId;
public OrderProcessor(String orderId) {
this.orderId = orderId;
}
@Override
public void run() {
System.out.println("Procesando pedido: " + orderId + " en el hilo " + Thread.currentThread().getName());
// Aquí puede haber un procesamiento largo...
}
}
Creamos e iniciamos los hilos:
public class Main {
public static void main(String[] args) {
Thread thread1 = new Thread(new OrderProcessor("ORDER-001"));
Thread thread2 = new Thread(new OrderProcessor("ORDER-002"));
thread1.start();
thread2.start();
}
}
Salida esperada:
Procesando pedido: ORDER-001 en el hilo Thread-0
Procesando pedido: ORDER-002 en el hilo Thread-1
Ejemplo 2: Hilo con parámetro mediante expresión lambda (Java 8+)
Si la tarea es sencilla, puedes prescindir de una clase separada.
public class Main {
public static void main(String[] args) {
String user1 = "Vasya";
String user2 = "Katya";
Thread thread1 = new Thread(() -> {
System.out.println("Hola, " + user1 + " desde " + Thread.currentThread().getName());
});
Thread thread2 = new Thread(() -> {
System.out.println("Hola, " + user2 + " desde " + Thread.currentThread().getName());
});
thread1.start();
thread2.start();
}
}
¿Por qué no usar setters/getters para pasar parámetros?
Si pasas parámetros mediante setters o campos públicos, existe el riesgo de que otro hilo cambie el valor justo durante la ejecución. Esto puede provocar errores difíciles de detectar. Es mejor hacer los campos final y pasarlos a través del constructor.
2. Prioridades de los hilos
En Java, cada hilo tiene una prioridad — un entero de 1 a 10 que le indica al planificador (scheduler) cuán «importante» es ese hilo en comparación con otros. Por defecto, todos los hilos tienen prioridad 5 (Thread.NORM_PRIORITY).
Importante: la prioridad es solo una «sugerencia» para el sistema operativo. No es garantía de que un hilo con prioridad 10 vaya a ejecutarse más rápido que uno con prioridad 1. Todo depende del SO, su configuración y la carga actual.
¿Cómo establecer la prioridad de un hilo?
La clase Thread tiene los métodos:
- setPriority(int newPriority)
- getPriority()
Y tres constantes estándar:
- Thread.MIN_PRIORITY (1)
- Thread.NORM_PRIORITY (5)
- Thread.MAX_PRIORITY (10)
Ejemplo 3: Establecer la prioridad de un hilo
public class PriorityDemo {
public static void main(String[] args) {
Runnable task = () -> {
System.out.println("Hilo " + Thread.currentThread().getName() +
" con prioridad " + Thread.currentThread().getPriority());
};
Thread low = new Thread(task, "LowPriority");
Thread norm = new Thread(task, "NormalPriority");
Thread high = new Thread(task, "HighPriority");
low.setPriority(Thread.MIN_PRIORITY); // 1
norm.setPriority(Thread.NORM_PRIORITY); // 5
high.setPriority(Thread.MAX_PRIORITY); // 10
low.start();
norm.start();
high.start();
}
}
Salida esperada (¡el orden de las líneas no está garantizado!):
Hilo LowPriority con prioridad 1
Hilo HighPriority con prioridad 10
Hilo NormalPriority con prioridad 5
¿Afecta la prioridad al orden de ejecución?
En la mayoría de los casos — no. Las prioridades pueden influir en cuánto tiempo de CPU se le asigna a un hilo, pero no garantizan el orden de inicio o finalización. No bases la lógica del programa en las prioridades — úsalas como «pistas» suaves, por ejemplo, para que un hilo en segundo plano no estorbe al principal.
Tabla: constantes de prioridad de hilos
| Constante | Valor | Descripción |
|---|---|---|
|
1 | La prioridad más baja |
|
5 | Prioridad normal |
|
10 | La prioridad más alta |
3. Nombrar hilos
El nombre de un hilo es como un «apodo» en el mundo de la multitarea. Cuando tienes decenas de hilos, depurar es más fácil si en el log, en lugar de "Thread-7", ves "FileUploader-1". Esto es especialmente importante al analizar logs y buscar errores.
¿Cómo establecer el nombre de un hilo?
Puedes indicar el nombre directamente en el constructor de Thread o establecerlo con el método setName. Para conocer el nombre actual — getName.
Thread t = new Thread(() -> {
System.out.println("¡Estoy trabajando!");
}, "MyThreadName");
t.start();
Ejemplo 4: Hilos con nombre
public class NamedThreads {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
System.out.println("Soy un hilo: " + Thread.currentThread().getName());
}, "Downloader");
Thread threadB = new Thread(() -> {
System.out.println("Soy un hilo: " + Thread.currentThread().getName());
});
threadB.setName("Uploader");
threadA.start();
threadB.start();
}
}
Salida esperada:
Soy un hilo: Downloader
Soy un hilo: Uploader
4. Práctica: varios hilos con diferentes parámetros, prioridades y nombres
Unamos todo en un ejemplo: cada pedido es un hilo separado con su propio nombre y prioridad.
public class OrderProcessor implements Runnable {
private final String orderId;
private final int processingTimeMs;
public OrderProcessor(String orderId, int processingTimeMs) {
this.orderId = orderId;
this.processingTimeMs = processingTimeMs;
}
@Override
public void run() {
System.out.println("[" + Thread.currentThread().getName() + "] Inició el procesamiento del pedido " + orderId +
" (prioridad " + Thread.currentThread().getPriority() + ")");
try {
Thread.sleep(processingTimeMs); // simulación de trabajo
} catch (InterruptedException e) {
System.out.println("[" + Thread.currentThread().getName() + "] ¡Interrumpido!");
}
System.out.println("[" + Thread.currentThread().getName() + "] Terminó de procesar el pedido " + orderId);
}
public static void main(String[] args) {
Thread fastOrder = new Thread(new OrderProcessor("FAST-ORDER", 500), "FastOrderThread");
Thread normalOrder = new Thread(new OrderProcessor("NORMAL-ORDER", 1000), "NormalOrderThread");
Thread slowOrder = new Thread(new OrderProcessor("SLOW-ORDER", 2000), "SlowOrderThread");
fastOrder.setPriority(Thread.MAX_PRIORITY);
normalOrder.setPriority(Thread.NORM_PRIORITY);
slowOrder.setPriority(Thread.MIN_PRIORITY);
fastOrder.start();
normalOrder.start();
slowOrder.start();
}
}
Qué veremos:
- Cada hilo escribe qué pedido está procesando, su nombre y su prioridad.
- El tiempo de procesamiento se simula con Thread.sleep.
- El orden de finalización de los hilos puede no coincidir con la prioridad.
5. Matices y particularidades importantes
Paso de parámetros: ¡solo a través del constructor!
Es más seguro. Declara los parámetros como final: no podrán cambiarse tras crear el objeto y ningún otro hilo «colará» sus valores. Esto es crítico para prevenir condiciones de carrera.
Prioridades: no bases en ellas la lógica de negocio
Las prioridades son como pedirle al camarero: «¿Me pones el café un poco más rápido?». A veces funciona, a veces no. Es una recomendación para el SO, no una regla de ejecución.
Nombres de hilos: úsalos para depurar
Ahorra muchísimo tiempo al analizar logs. Acostúmbrate a poner nombres con significado desde el principio.
6. Errores típicos al trabajar con parámetros y prioridades de hilos
Error n.º 1: Pasar parámetros a través de campos públicos. Si declaras los parámetros como campos normales y los cambias después de iniciar el hilo, puedes obtener resultados impredecibles. Usa campos final y el constructor.
Error n.º 2: Esperar que la prioridad garantice el orden. ¿Pusiste Thread.MAX_PRIORITY y crees que el hilo será siempre el primero? No. No uses las prioridades para sincronizar o controlar la lógica.
Error n.º 3: Hilos sin nombre en los logs. Cuando en los logs solo hay «Thread-3», «Thread-7», es difícil encontrar al culpable. Da a los hilos nombres con significado usando el constructor o setName.
Error n.º 4: Usar el mismo objeto Runnable para varios hilos. Si el objeto Runnable guarda estado y lo pasas a varios hilos, «comparten» los parámetros — camino directo a condiciones de carrera. Crea un Runnable separado por hilo.
Error n.º 5: Pasar parámetros mediante métodos set. Si defines parámetros mediante métodos set* después de crear/iniciar el hilo, los valores pueden cambiar «al vuelo» — una condición de carrera clásica.
GO TO FULL VERSION