15 preguntas tipo test sobre todo el temario. Selecciona la respuesta correcta en cada pregunta.
🖥️ Proceso vs. Hilo (Thread)
PROCESO
Instancia de un programa en ejecución.
- ✓ Memoria Propia: Stack y Heap aislados.
- ✓ Aislado: Un fallo no afecta a otros procesos.
- ✗ Pesado: Lento para crear y comunicar.
Ejemplo: Abrir dos instancias de Notepad (dos procesos).
HILO (Thread)
Unidad de ejecución dentro de un proceso.
- ✓ Memoria Compartida: Mismo Heap, Stack propio.
- ✗ No Aislado: Un fallo afecta a todo el proceso.
- ✓ Ligero: Rápido para crear y comunicar.
Ejemplo: Escribir texto (hilo UI) y guardar (hilo de fondo) en un solo Notepad.
🔄 Ciclo de Vida de un Hilo
El objeto existe, pero el S.O. no sabe nada de él.
El hilo está en la cola del planificador, listo para ejecutarse.
El hilo está actualmente usando la CPU.
Estados de No Ejecución (Not Runnable)
BLOCKED
El hilo intenta entrar en un bloque `synchronized` pero otro hilo ya tiene el candado (monitor lock).
Vuelta a RUNNABLE: Cuando el candado es liberado.
WAITING
El hilo ha llamado a `objeto.wait()` o `hilo.join()` (sin tiempo).
Vuelta a RUNNABLE: Cuando es notificado (`notify()` / `notifyAll()`) o el hilo de `join()` muere.
TIMED_WAITING
El hilo ha llamado a `Thread.sleep(ms)`, `objeto.wait(ms)` o `hilo.join(ms)`.
Vuelta a RUNNABLE: Cuando el tiempo expira o es notificado.
El hilo ha muerto y no puede volver a iniciarse.
🔒 Sincronización: Problema y Solución
PROBLEMA: Condición de Carrera
Varios hilos leen y escriben en un recurso compartido (ej: `saldo`) al mismo tiempo.
Hilo A lee (100)
Hilo B lee (100)
Hilo A escribe (101)
Hilo B escribe (101) // ¡Depósito perdido!
Resultado: Datos corruptos e impredecibles.
SOLUCIÓN: `synchronized`
Crea una "sección crítica" o "monitor lock". Solo un hilo puede entrar a la vez.
// Hilo A entra y bloquea
saldo = saldo + 1;
// Hilo B espera (BLOCKED)
} // Hilo A sale y libera
Resultado: Operación atómica y datos consistentes.
📄 Métodos Clave de `Thread`
| Método | Descripción | Contexto |
|---|---|---|
.start() |
Inicia el hilo. Llama a run() en un nuevo hilo de ejecución. |
✅ OBLIGATORIO |
.run() |
Contiene el código que ejecutará el hilo. (No llamar directamente). | Implementar (Runnable) / Sobrescribir (Thread) |
.join() |
El hilo actual espera (se bloquea) hasta que el hilo t termine. |
Coordinación |
.sleep(ms) |
Pausa el hilo actual por 'ms' milisegundos. (Estado TIMED_WAITING). | Simulación / Pausa |
.interrupt() |
Envía una señal de interrupción al hilo. | Detención / Señalización |
.isAlive() |
Devuelve true si el hilo ha iniciado y no ha terminado. |
Verificación |
Thread.currentThread() |
Método estático. Devuelve la instancia del hilo actual. | Utilidad |
🤝 Sincronización y Comunicación (Clase `Object`)
| Método | Descripción | Contexto |
|---|---|---|
synchronized (bloque/método) |
Adquiere el candado (monitor lock) del objeto. Previene Condiciones de Carrera. | Atomicidad |
.wait() |
Libera el candado y pone al hilo en estado WAITING (suspensión pasiva). | Productor-Consumidor |
.notify() |
Despierta a UN hilo aleatorio que esté en wait() sobre ese objeto. |
Productor-Consumidor |
.notifyAll() |
Despierta a TODOS los hilos que estén en wait() sobre ese objeto. |
✅ RECOMENDADO |
⚖️ Comparativa de Estados de Espera
BLOCKED
Causa: Intentar entrar en un bloque `synchronized` que ya está ocupado.
Cómo sale: Automáticamente, cuando el otro hilo libera el candado.
Control: El programador no lo controla, es automático del monitor lock.
WAITING
Causa: Llamada explícita a `objeto.wait()` o `hilo.join()`.
Cómo sale: Llamada explícita a `objeto.notify()` o `notifyAll()` desde otro hilo.
Control: El programador lo controla para la comunicación entre hilos.
🖥️ Métodos Clave de `Process` y `ProcessBuilder`
| Método | Descripción |
|---|---|
ProcessBuilder(cmd) |
Configura el comando a ejecutar (ej: "notepad.exe" o "cmd", "/c", "echo"). |
builder.inheritIO() |
Redirige la salida del proceso hijo a la consola del padre. |
builder.start() |
Inicia el proceso externo y devuelve un objeto Process. |
process.waitFor() |
Bloquea el hilo actual (Java) hasta que el proceso externo termine. |
process.exitValue() |
Devuelve el código de salida del proceso (0 = éxito). Solo usar después de waitFor(). |
process.getInputStream() |
Obtiene el stream para LEER la SALIDA del proceso externo. |
⚠️ IMPORTANTE - Errores Comunes
- • Error: Llamar a `hilo.run()` en lugar de `hilo.start()`.
Causa: Ejecuta el código en el hilo principal, no en uno nuevo. - • Error: Usar `if(lista.isEmpty()) wait();` en lugar de `while(...)`.
Causa: Vulnerable a "Spurious Wakeups" (despertares falsos). - • Error: Llamar a `wait()` o `notify()` fuera de un bloque `synchronized`.
Causa: Lanza `IllegalMonitorStateException`. - • Error: Usar `Thread.sleep()` para sincronizar (espera activa).
Causa: Ineficiente y poco fiable. Usar `wait()`/`notify()`.
💡 Consejos para código:
- • `start()` crea un hilo, `run()` no.
- • `synchronized` protege datos compartidos.
- • `join()` espera a que un hilo muera.
- • `wait()` libera el candado, `sleep()` no lo hace.
- • `process.getInputStream()` es la SALIDA del proceso externo.