Scène d'attente
La scène typique de notification d'attente est généralement liée aux deux contenus suivants:
1. Variable d'état
Lorsque les fils doivent attendre, il est toujours causé par certaines conditions. Par exemple, remplissant la file d'attente, lorsque l'élément de file d'attente est plein, le fil doit cesser de fonctionner. Lorsque les éléments de file d'attente sont vacants, continuez leur propre exécution.
2. Prédicat de condition
Lorsque le thread est déterminé s'il faut saisir l'attente ou se réveille de notifier, il est nécessaire de tester si les conditions d'état sont remplies. Par exemple, en ajoutant des éléments à la file d'attente, la file d'attente est pleine, il bloque donc le thread actuel. fil de discussion." À l'heure actuelle, le processus d'attente de l'élément sera éveillé, puis jugera s'il y a vraiment de la place pour la file d'attente actuelle. prochain sillage -up.
3. Fitre de condition
Chaque objet a une file d'attente de condition construite.
Avis
L'attente et les notifications sont une partie importante du mécanisme de synchronisation Java. Combinée à l'utilisation de mots clés synchronisés, de nombreux excellents modèles synchrones peuvent être établis, tels que le modèle producteur-consommateur. Mais lorsque vous utilisez la fonction function (), notify (), notifyall (), vous devez accorder une attention particulière aux points suivants:
Wait (), notify (), notifyall () Les méthodes n'appartiennent pas à la classe de threads, mais appartiennent à la classe de fondation objet, c'est-à-dire que chaque objet a les fonctions d'attente (), notify () et notify (). Étant donné que chaque objet est verrouillé, le verrou est la base de chaque objet, donc la méthode de fonctionnement du verrouillage est également la plus basique.
Appelez l'OBJ Wait () et Notify () Méthode, vous devez obtenir le verrouillage OBJ, c'est-à-dire que vous devez être écrit dans le segment de code synchronisé (OBJ) {...}.
Après avoir appelé obj.wait (), le thread A libère le verrou de l'OBJ, sinon le thread B ne peut pas obtenir le verrou OBJ, et il ne pourra pas réveiller le fil A dans le code synchronisé (obj) {...} segment.
Lorsque la méthode obj.wait () revient, le thread A doit réaccuser le verrouillage OBJ pour continuer l'exécution.
Si les threads A1, A2, A3 sont dans obj.wait (), le thread B appelle obj.notify () ne peut que réveiller l'un des threads A1, A2, A3 (dont un est déterminé par JVM).
Si le fil B appelle obj.notifyall (), il peut tous réveiller le fil d'attente A1, A2, A3, mais le fil d'attente pour continuer à exécuter la phrase suivante d'Obj.Wait (), vous devez obtenir un verrou OBJ. Par conséquent, les threads A1, A2, A3 n'ont qu'une seule chance d'obtenir des verrous et de continuer à s'exécuter.
Lorsque le thread B appelle obj.notify () ou obj.notifyall (), le thread B maintient le verrouillage obj. Jusqu'à ce que le thread B quitte le bloc de code synchronisé et relâche le verrouillage OBJ, un dans le thread A1, A2, A3 a la possibilité d'obtenir le verrouillage de l'objet et de continuer à s'exécuter.
Par exemple le code
La structure de code typique de l'opération d'attente du thread est la suivante:
public void test () lève InterruptedException {synchronisé (obj) {while (! Contidition) {obj.wait ();}}}}}}}}}
Pourquoi les opérations obj.wait () doivent-elles être situées dans le cycle? Il y a plusieurs raisons principales:
1. Un verrouillage d'objet peut être utilisé pour protéger plusieurs variables d'état. Par exemple, un certain objet verrouille l'OBJ pour protéger les deux variables d'état A et B. Lorsque les conditions d'une affirmation ne sont pas établies, l'opération d'attente se produit. Maintenant, si une opération d'une variable d'état a se produit, l'opération Notifyall est appelée OBJ, tous les threads de la file d'attente correspondant à l'OBJ sont éveillés. Car B est également éveillé pour le moment, vous devez donc recycler si l'état de B est respecté pour être respecté.
2. Les conditions du même état de plusieurs threads sont affirmées. Par exemple, la scène de l'ajout d'éléments à la file d'attente, la file d'attente actuelle est pleine et plusieurs threads veulent ajouter des éléments à l'intérieur, donc ils sont tous. À l'heure actuelle, un autre fil a retiré un élément de la file d'attente et a appelé l'opération Notifyall pour réveiller tous les threads, mais un seul fil pourrait ajouter un élément à la file d'attente.
3. Faux Awakening. Sans être informé, interrompre ou sur, le fil a été automatiquement éveillé. Bien que cette situation se produise rarement dans la pratique, cette situation peut être éliminée en attendant le cycle.