Quando si lavora con programmi multi-threaded ci si potrebbe chiedere se sia meglio sincronizzare i processi mediante una serie di wait()/notify() oppure invocazioni del metodo join(). Anzitutto occorre chiarire la semantica dei metodi:
  • wait()/notify() sospendono e risvegliano un processo sul monitor associato all'oggetto sul quale viene richiamto il metodo;
  • join() sospende il processo corrente fino a quando il Thread sul quale il metodo è stato chiamato non ha terminato la sua esecuzione (ossia è usito da run()).
Dalla semplice descrizione di cui sopra se ne deduce che il metodo join() è molto utile quando si ha un thread "padre" che deve attendere la fine dell'esecuzione di tutti i suoi figli, come pure se si hanno processi che devono continuare la propria esecuzione solo dopo che altri processi hanno terminato il loro lavoro. Il meccanismo wait()/notify() risulta invece più flessibile, poiché può sincronizzare processi che non stanno terminando, e quindi che potrebbero riprendere il loro lavoro. Quello che però molto spesso inganna è che il metodo join() è equivalente ad una buona sincronizzazione con wait()/notify(), e quindi non esiste nessuna potenziale differenza di performance nell'utilizzo di un metodo o dell'altro. Infatti, spulciando il codice sorgente di java.lang.Thread si scopre che il metodo notify() viene implementato con una "semplice" wait(), e che di conseguenza quando il thread termina provvede a risvegliare i processi sospesi sul suo monitor.

 public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;

if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

The article Wait/Notify vs Join has been posted by Luca Ferrari on September 4, 2008