NUCLI 5 · Sessió 2 · Sortida, error i temps màxim
Els fluxos
Sistema a restaurar: Canals d'entrada i sortida dels fills
- Alerta
- Manual
- Reptes
- Mòdul
Aquest nucli ja està en marxa. Pots tornar-lo a jugar per repassar, però la puntuació desada no canviarà.
Manual del nucli
0 / 3Desbloqueja les 3 pàgines del manual per obrir els reptes. Llegeix-les bé: els reptes en pregunten els detalls.
Els tres fluxos, vistos des del pare
Els noms enganyen: estan pensats des del punt de vista del pare.
p.getInputStream(): el pare hi llegeix el que el fill escriu ambSystem.out.p.getErrorStream(): el pare hi llegeix el que el fill escriu ambSystem.err.p.getOutputStream(): el pare hi escriu i al fill li arriba perSystem.in.
Entre pare i fill hi ha una memòria intermèdia (buffer) petita. Si el fill escriu molt i el pare no la buida, s'omple i el fill es bloqueja esperant lloc. Si a més el pare està fent waitFor(), s'esperen l'un a l'altre per sempre: un interbloqueig.
Solucions: llegir la sortida abans de waitFor(), llegir cada flux en un fil a part, fusionar-los amb redirectErrorStream(true), enviar-los a un fitxer o fer inheritIO().
Exemple 3: un fil lector per a cada flux
Si vols la sortida i l'error per separat, no els pots llegir un darrere l'altre: mentre llegeixes el primer, el segon es pot omplir. L'exemple 3 posa un fil a llegir cadascun.
Process p = new ProcessBuilder(Jvm.ordre(Tasca.class, nom, "1")).start();
Thread fout = llegeixEnSegonPla(p.getInputStream(), " [out] ");
Thread ferr = llegeixEnSegonPla(p.getErrorStream(), " [ERR] ");
int codi = p.waitFor();
fout.join();
ferr.join();| Fragment | Què fa |
|---|---|
Jvm.ordre(Tasca.class, nom, "1") | Construeix l'ordre per executar la classe Tasca del mateix projecte com a procés fill. |
llegeixEnSegonPla(p.getInputStream(), …) | Engega un fil que copia la sortida estàndard del fill a la consola. |
llegeixEnSegonPla(p.getErrorStream(), …) | Un altre fil per a la sortida d'error: tots dos es buiden alhora. |
p.waitFor() | Ara sí que es pot esperar el fill: ningú no es quedarà bloquejat. |
fout.join(); ferr.join(); | Espera que els fils lectors hagin acabat de buidar els fluxos abans de continuar. |
Exemple 4: no esperar mai per sempre
waitFor(temps, unitat) espera com a molt aquell temps i retorna un booleà: true si el fill ha acabat a temps, false si no. Si no ha acabat, el matem en dos passos.
boolean haAcabat = p.waitFor(3, TimeUnit.SECONDS);
if (haAcabat) {
System.out.println("Ha acabat amb codi " + p.exitValue());
} else {
p.destroy();
if (!p.waitFor(2, TimeUnit.SECONDS)) {
p.destroyForcibly();
}
System.out.println("Viu? " + p.isAlive() + " · codi " + p.exitValue());
}| Fragment | Què fa |
|---|---|
p.waitFor(3, TimeUnit.SECONDS) | Espera un màxim de 3 segons. No retorna el codi: retorna si ha acabat o no. |
p.exitValue() | Aquí és segur: només hi arribem si el fill ja ha acabat. |
p.destroy() | Petició educada d'acabar: el fill pot tancar les seves coses. |
p.destroyForcibly() | Si en 2 segons no ha fet cas, el matem a la força. |
p.isAlive() | Comprovació final: ha de ser false. |
Nucli restaurat · Canals d'entrada i sortida dels fills
Canals desembussats: cap fill no espera ningú i cap pare no espera per sempre.
- XP
- 0
- Bonus ratxa
- 0
- Errors
- 0
- Pistes
- 0
- Estrelles
- ☆☆☆
Anota la lletra i la seva posició: al kernel hauràs de compondre l'ordre de reinici.