M0490 · Programación de servicios y procesos · Resumen fácil + quiz
Cada proceso tiene un PCB con lo que el SO necesita para ejecutarlo:
| Proceso | Hilo | |
|---|---|---|
| Memoria | Propia, aislada | Compartida con su proceso |
| Coste | Pesado, caro de crear | Ligero, rápido |
| Seguridad | Más seguro (no corrompe a otros) | Si un hilo falla, puede tumbar todo el proceso |
| Problema | Comunicarse cuesta más (IPC) | Hay que sincronizar |
Hay más procesos que CPUs, así que el planificador decide quién se ejecuta y cuándo.
| Tipo | Qué hace |
|---|---|
| Largo plazo | Pasa programas del disco a memoria (los convierte en procesos). |
| Medio plazo | Suspende/reanuda procesos; mueve a la zona de intercambio (swap) si el sistema está saturado. |
| Corto plazo (CPU) | Elige qué proceso preparado entra a la CPU. El más importante para el rendimiento. |
| Algoritmo | Idea | 👍 | 👎 |
|---|---|---|---|
| FCFS (First Come First Served) | El primero que llega, primero que se ejecuta | Simple | Uno largo hace esperar a todos (efecto convoy) |
| SJN (Shortest Job Next) | Primero el más corto | Tiempo medio de respuesta bajo | Perjudica a los largos |
| Round Robin | Cada uno tiene un tiempo fijo (quantum); si no acaba, al final de la cola | Equitativo | Quantum corto → muchos cambios de contexto; largo → se parece a FCFS |
| Prioridades | Siempre el de más prioridad | Atiende lo urgente | Inanición: los de baja prioridad esperan siempre |
| Paralela | Distribuida | |
|---|---|---|
| Dónde | Varios núcleos de un mismo ordenador | Varios ordenadores en red |
| Memoria | Compartida (misma RAM) | Cada máquina la suya |
| Comunicación | Memoria compartida | Por red |
| Ejemplo | Procesar una imagen con 4 núcleos | Google Search, torrent (P2P), juegos online |
| Linux / Unix | Para qué |
|---|---|
ps / ps -ef | Procesos activos (con PID y PPID) |
top / htop | Lista en tiempo real (htop = más visual) |
kill PID | Envía señal SIGTERM (pide parar) |
kill -9 PID | SIGKILL: lo mata al instante |
jobs, fg, bg | Primer / segundo plano en la shell |
| Windows | |
| Administrador de tareas | Ver y finalizar procesos |
tasklist | Listar procesos |
taskkill /PID <pid> | Finalizar un proceso |
Cómo se pasan datos los procesos. Técnicas: ficheros y pipes (sencillas), sockets, memoria compartida y colas de mensajes (más potentes).
ls | grep .java → la salida de un proceso es la entrada del otro.Process p = Runtime.getRuntime().exec("notepad"); // lanza un proceso externo
p.waitFor(); // espera a que acabe
Process| Método | Qué hace |
|---|---|
getInputStream() | Leer la salida estándar del proceso (lo que imprime) |
getOutputStream() | Escribir en su entrada estándar (como el teclado) |
getErrorStream() | Leer su salida de error |
waitFor() | Esperar a que termine |
exitValue() | Código de salida |
getInputStream() lee la salida del proceso (es "input" desde el punto de vista de Java).Más control de argumentos, permite redirigir entrada/salida y es más claro.
ProcessBuilder pb = new ProcessBuilder("ls", "-l"); // orden y argumentos separados
pb.redirectOutput(new File("salida.txt")); // también redirectInput / redirectError
Process p = pb.start(); // ejecuta
Pipes en Java: conectar la salida de un proceso (ls / dir) a la entrada de otro (grep / findstr). Java lo automatiza con ProcessBuilder.startPipeline(...).
Todo programa Java empieza con el hilo principal (main thread). Dos formas de crear hilos:
// 1) Heredar de Thread
class MiHilo extends Thread {
public void run() { System.out.println("Hola desde un hilo"); }
}
new MiHilo().start();
// 2) Implementar Runnable (⭐ recomendada)
class MiTarea implements Runnable {
public void run() { System.out.println("Hola"); }
}
new Thread(new MiTarea()).start();
start(), NUNCA a run() directamente: si llamas a run() se ejecuta en el mismo hilo, no en uno nuevo.Por qué Runnable es mejor: tu clase puede heredar de otra a la vez (Java no tiene herencia múltiple) y se reutiliza mejor el código.
| Método | Qué hace |
|---|---|
sleep(ms) | Pausa el hilo X milisegundos y libera la CPU |
join() | El padre espera a que el hijo termine |
interrupt() | Pide que pare (no lo mata). No usar stop(): deja recursos abiertos |
setPriority(n) | Prioridad de 1 (MIN) a 10 (MAX). Por defecto 5 (NORM) |
Los estados de un hilo están en el enum Thread.State: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
count++ no es atómico → con varios hilos da resultados erróneos.// Método sincronizado: bloquea el objeto entero
public synchronized void incrementar() { count++; }
// Bloque sincronizado: solo bloquea la parte crítica (más eficiente)
public void incrementar() {
synchronized (this) { count++; }
}
synchronized(obj), los demás que quieran entrar en bloques sincronizados del mismo objeto esperan.Hilo 1 bloquea cuenta A y quiere B; hilo 2 bloquea cuenta B y quiere A → ninguno avanza.
Solución: establecer un orden global de bloqueo (todos bloquean siempre en el mismo orden, p. ej. por id de cuenta).
No basta con no pisarse: a veces un hilo tiene que avisar a otro (p. ej. "ya hay datos").
wait(): el hilo se duerme y suelta el lock hasta que le avisen.notify(): despierta a un hilo que espera. notifyAll(): a todos.synchronized (obj) {
while (!condicion) { // ⚠️ while, NO if
obj.wait();
}
// hacer el trabajo
obj.notifyAll();
}
wait().wait().notify() para despertar al otro.