Senza avere imposizioni particolari e senza avere altri dettagli in più, a me verrebbe innanzitutto da pensare
cosa deve fare lo studente come sequenza di operazioni. A livello concettuale:
- si mette in attesa di essere chiamato
- una volta chiamato, occupa l'aula per un tot di tempo
- una volta finito, abbandona l'aula
Tradotto in codice, il run() dello Studente potrebbe essere "ad occhio" qualcosa del genere:
public void run() {
Aula aula = areaAttesa.attendiChiamata();
try {
// qui si attende del tempo, es. con una sleep()
} finally {
aula.abbandona();
}
}
Dove areaAttesa sarebbe un singolo oggetto "comune" a tutti quanti (studenti e docente). E attendiChiamata() è "bloccante" ovvero il thread (dello studente) va in sospensione finché qualcuno "chiama" lo studente. Quando attendiChiamata() si sblocca vuol dire che lo studente è entrato nell'aula ed infatti riceve un oggetto Aula. Attende del tempo e alla fine (in qualunque caso!) abbandona l'aula.
E' un flusso molto semplicistico ma come concetto "fila" secondo me.
Il punto/problema è fare il resto. Dal testo si evince che il docente-thread debba avere un ruolo "attivo" (avendo un suo flusso di esecuzione). Ed è il docente che deve scegliere (con la logica descritta) l'aula in cui far accomodare lo studente. Quindi la scelta dell'aula non può essere fatta
solamente in quel attendiChiamata() (altrimenti a che servirebbe il docente come thread?).
Visto così mi verrebbe da pensare di fare nell'oggetto areaAttesa una "coda" sincrona e bloccante. Gli studenti si accodano con ordine FIFO nella coda e stanno in attesa.
Dall'altra parte, su un ALTRO flusso di esecuzione, il docente-thread estrae con ordine appunto FIFO il "prossimo" studente, determina l'aula e (attenzione!) fa in modo da assegnare l'oggetto Aula allo studente e lo sblocca, in modo che attendiChiamata() esca finalmente con
quel oggetto Aula.