Módulo: Concurrencia
Este módulo forma parte del curso de Java. Incluye 3 lecciones .
Concurrencia en Java
La concurrencia representa uno de los paradigmas más importantes en el desarrollo de aplicaciones modernas. En Java, este concepto permite que múltiples hilos de ejecución (threads) trabajen simultáneamente, aprovechando al máximo los recursos del sistema y mejorando significativamente el rendimiento de las aplicaciones.
Fundamentos de la programación concurrente
La programación concurrente surge de la necesidad de ejecutar múltiples tareas de forma simultánea. Mientras que un programa secuencial ejecuta una instrucción tras otra, un programa concurrente puede realizar varias operaciones al mismo tiempo, como procesar datos mientras descarga archivos de internet o actualizar la interfaz gráfica mientras realiza cálculos complejos.
Java incorpora soporte nativo para concurrencia desde sus primeras versiones. El lenguaje proporciona herramientas integradas que permiten crear, gestionar y sincronizar hilos de ejecución de manera eficiente y segura.
Hilos en Java
Un hilo (thread) es la unidad básica de ejecución concurrente en Java. Cada hilo representa un flujo independiente de instrucciones que puede ejecutarse en paralelo con otros hilos dentro del mismo proceso.
La clase Thread constituye el elemento fundamental para trabajar con concurrencia:
public class MiHilo extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Hilo: " + Thread.currentThread().getName() + " - Iteración: " + i);
try {
Thread.sleep(1000); // Pausa de 1 segundo
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
Alternativamente, Java ofrece la interfaz Runnable, que proporciona mayor flexibilidad al separar la lógica de ejecución de la gestión del hilo:
public class TareaRunnable implements Runnable {
private String nombre;
public TareaRunnable(String nombre) {
this.nombre = nombre;
}
@Override
public void run() {
System.out.println("Ejecutando tarea: " + nombre);
// Lógica de la tarea
}
}
// Uso
Thread hilo = new Thread(new TareaRunnable("Procesamiento de datos"));
hilo.start();
Estados y ciclo de vida de los hilos
Los hilos en Java atraviesan diferentes estados durante su ciclo de vida. Comprender estos estados resulta fundamental para gestionar correctamente la concurrencia:
- NEW: El hilo ha sido creado pero aún no ha comenzado su ejecución
- RUNNABLE: El hilo está ejecutándose o listo para ejecutarse
- BLOCKED: El hilo está bloqueado esperando un monitor de sincronización
- WAITING: El hilo espera indefinidamente a que otro hilo realice una acción específica
- TIMED_WAITING: El hilo espera durante un tiempo determinado
- TERMINATED: El hilo ha completado su ejecución
Sincronización y acceso concurrente
Cuando múltiples hilos acceden a recursos compartidos, pueden surgir problemas de consistencia de datos. Java proporciona mecanismos de sincronización para coordinar el acceso a estos recursos.
La palabra clave synchronized permite crear secciones críticas donde solo un hilo puede ejecutar código simultáneamente:
public class Contador {
private int valor = 0;
public synchronized void incrementar() {
valor++; // Operación atómica protegida
}
public synchronized int obtenerValor() {
return valor;
}
}
Los bloques sincronizados ofrecen un control más granular sobre la sincronización:
public class GestorRecursos {
private final Object lock = new Object();
private List<String> recursos = new ArrayList<>();
public void agregarRecurso(String recurso) {
synchronized(lock) {
recursos.add(recurso);
System.out.println("Recurso agregado: " + recurso);
}
}
}
Herramientas avanzadas de concurrencia
Java proporciona el paquete java.util.concurrent con herramientas especializadas para escenarios de concurrencia complejos. Los ExecutorService simplifican la gestión de pools de hilos:
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Procesando tarea " + taskId +
" en hilo: " + Thread.currentThread().getName());
// Simular trabajo
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
executor.shutdown();
Las colecciones concurrentes como ConcurrentHashMap
y BlockingQueue
proporcionan estructuras de datos thread-safe optimizadas para entornos concurrentes:
ConcurrentHashMap<String, Integer> mapa = new ConcurrentHashMap<>();
BlockingQueue<String> cola = new LinkedBlockingQueue<>();
// Operaciones thread-safe sin sincronización explícita
mapa.put("clave", 100);
cola.offer("elemento");
Comunicación entre hilos
Los hilos necesitan comunicarse y coordinarse para trabajar eficientemente. Java ofrece varios mecanismos para esta comunicación, desde los métodos tradicionales wait()
y notify()
hasta herramientas modernas como CountDownLatch
y Semaphore
.
La programación concurrente en Java requiere un equilibrio cuidadoso entre rendimiento y seguridad. Los desarrolladores deben considerar aspectos como la prevención de deadlocks, la gestión eficiente de recursos y la escalabilidad de sus soluciones concurrentes.
Otros módulos de este curso
Lecciones de este módulo
Explora todas las lecciones disponibles en Concurrencia
Todos los módulos del curso
Navega entre los módulos de Java
Explora más sobre Java
Descubre más recursos de Java

Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Java es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.