Frengo ha scritto:
Ho corretto la sintassi del passaggio del Buffer, la condizione del while nel metodo get e ho tolto l'arrayList, inserendo invece una semplice variabile int e un booleano di controllo.
Il codice ora mi pare proprio che sia funzionalmente corretto, cioè hai gestito i test e i vari passi in maniera di per sé appropriata.
Ci sono comunque queste piccole annotazioni che potrei ancora fare:
1) Io personalmente avrei messo
boolean presente (presente=true allora c'è un valore), ovvero al contrario del tuo. Ma è solo questione di gusti, se è fatto correttamente, vale l'uno o l'altro.
2) Nel while puoi togliere le parentesi interne:
while (vuoto==true ||
(numero<min || numero>max
) ) {
while (vuoto==true || numero<min || numero>max) {
il significato non cambia, || è un operatore con "short-circuit": se vuoto è true, il resto della espressione NON lo valuta nemmeno!
3) Al fondo del get hai messo:
int a = numero;
vuoto = true;
notifyAll();
return a;
è
corretto. Ma lo si può scrivere più semplicemente:
vuoto = true;
notifyAll();
return numero;
Considera sempre che lì sei in un metodo
synchronized quindi, a parte il momento di "sospensione" nel wait() (che rilascia il lock), lì dentro hai la
esclusività del lock!! Mentre vengono eseguite queste operazioni,
nessun altro thread può interferire, né eseguire un put o get.
Quindi anche se ritorni il numero
dopo aver messo vuoto = true (che sembra una incoerenza), in realtà nella interezza "atomica" del get() è comunque corretto.
4) Hai ancora il catch "vuoto" di InterruptedException, che non è molto bello. Ragiona su quanto ho già detto prima riguardo le interruzioni (se hai dubbi, chiedi).
Frengo ha scritto:
Il programma viene ora eseguito, a quanto pare QUASI correttamente.
Quello che devi verificare è che la sequenza di numeri 1-5 generata da Produttore sia la stessa presa da ConsumatoreUno e che la sequenza di numeri 6-10 generata sia la stessa presa da ConsumatoreDue.
Se questo è corretto, la logica è corretta.
Se la sequenza generata fosse es. 4 7 6 3 2 9 5 10 1 8
Devi guardare che i soli output di ConsumatoreUno diano in sequenza 4 3 2 5 1
E separatamente guardare che i soli output di ConsumatoreDue diano in sequenza 7 6 9 10 8
Frengo ha scritto:
L'unica cosa che non mi spiego è come sia possibile che, a volte, il consumatore prenda un numero prima che esso venga generato dal produttore xD
No, quello che hai detto non può succedere (non avrebbe senso). Ti stai basando solo su quello che vedi in output ma la chiamata a put/get è distinta dal println e l'insieme di queste due operazioni NON è atomico! Quindi con tempistiche un po' "sfortunate" (specialmente su macchine multi-core)
può assolutamente capitare che a livello temporale le istruzioni vengano "intercalate" nel seguente modo:
tempo thread Produttore thread ConsumatoreUno
| :
| buffer.put(num); :
| :
| : int num = buffer.get(min,max);
| : System.out.println("Consumatore uno prende "+num);
| :
| System.out.println("Produttore genera "+num); :
| :
?
Ma il get è comunque subordinato (quindi
dopo) al put, questo non può cambiare (se è fatto tutto correttamente).