Après avoir exécuté wait (), combien de temps un thread attend-il s'il n'est pas notifié par les autres threads?

Aug 16 2020

Dans l'exemple ci-dessous, comme le thread principal ne reçoit pas de notification du thread enfant, il doit attendre indéfiniment. Mais le thread principal est exécuté et la sortie de l'exemple ci-dessous est:

c
l
total: 19900

Pourquoi le thread principal est-il exécuté?

public class ThreadX extends Thread {
    static int total = 0;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 200; i++) {
                total = total + i;
            }
            System.out.println("c");

        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadX t = new ThreadX();

        t.start();
        synchronized (t) {
            t.wait();
            System.out.println("l");
        }

        System.out.println("total: " + total);

    }
}

Réponses

10 akuzminykh Aug 16 2020 at 09:58

Réponse à la question-corps

Découvrez Thread#join(long):

[...] Lorsqu'un thread se termine, la this.notifyAllméthode est appelée. [...]

Notez que cela Thread#join()appelle cette fonction avec 0, ce qui signifie pour toujours.

[...] Un timeout de 0 signifie attendre indéfiniment.

Donc, dans votre cas, il tn'appelle ici que notifyAlllorsqu'il se termine, ce qui notifie le thread principal qui attend t.


Ce comportement peu intuitif est la raison pour laquelle ils écrivent ce qui suit dans la documentation:

Il est recommandé que les applications utilisent pas wait, notifyou notifyAllsur les Threadinstances.

Réponse à la question-titre

Départ Object#wait(ou JLS (17.2.1. Attendre) ):

Un thread peut se réveiller sans être notifié, interrompu ou expiré, ce que l'on appelle un faux réveil. Bien que cela se produise rarement dans la pratique, les applications doivent se prémunir contre cela en testant la condition qui aurait dû provoquer le réveil du thread, et en continuant à attendre si la condition n'est pas satisfaite.

Ainsi, les threads en Java peuvent se réveiller à tout moment. Un faux réveil n'est pas très probable, mais cela peut arriver.