Différence entre wait () et sleep ()


1204

Quelle est la différence entre a wait()et sleep()dans Threads?

Est-ce que je comprends qu'un wait()thread -ing est toujours en mode de fonctionnement et utilise des cycles CPU mais qu'un sleep()-ing ne consomme aucun cycle CPU correct?

Pourquoi avons-nous les deux wait() et sleep(): comment leur mise en œuvre varie-t-elle à un niveau inférieur?


50
très bonne question. la sémantique des deux est facile à confondre.
Andreas Petersson le

1
Très belles questions mais elles sont 2 en une. Pourquoi avons-nous les deux n'est pas la même chose que la façon dont ils peuvent (et ne sont pas!) Mis en œuvre à un niveau inférieur. J'ai répondu à cela aussi.
estani

Supposons qu'un thread A se trouve dans un bloc synchronisé, et pendant qu'il se trouve dans l'unité centrale de traitement de ce thread est pris et donné à un autre thread B. maintenant dans quel état le thread A ira, les autres threads en attente sur ce bloc synchronisé entreront-ils maintenant maintenant ?
Peter

1
Voici un bon article le décrivant: qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man

3
son EXCATLY l'opposé - sleep "utilise" tous ses cycles CPU disponibles mais puisque le thread sera en "WAITING" - état ceux-ci peuvent être cédés si nécessaire - en fait la plupart des systèmes d'exploitation produisent automatiquement les cycles SI c'est possible, donc votre thread ne créera pas de charge CPU réelle ... cependant, il le fera sur les anciens systèmes d'exploitation. Object.wait (), d'autre part, n'utilise JAMAIS de cycle (tout en n'étant pas notifié) car il est réalisé via des interruptions logicielles dans de nombreux cas - des verrous privés, transitoires et transparents, implémentés par la JVM. Thread.sleep est une mauvaise pratique.
specializt

Réponses:


838

Un waitpeut être "réveillé" par un autre thread appelant notifyle moniteur qui est attendu alors qu'un sleepne peut pas. De plus, un wait(et notify) doit se produire dans un bloc synchronizedsur l'objet moniteur alors que sleepne:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

À ce stade, le thread en cours d'exécution attend et libère le moniteur . Un autre fil peut faire

synchronized (mon) { mon.notify(); }

(sur le même monobjet) et le premier thread (en supposant que c'est le seul thread en attente sur le moniteur) se réveillera.

Vous pouvez également appeler notifyAllsi plusieurs threads attendent sur le moniteur - cela les réveillera tous . Cependant, un seul des threads pourra saisir le moniteur (rappelez-vous que le waitest dans un synchronizedbloc) et continuer - les autres seront alors bloqués jusqu'à ce qu'ils puissent acquérir le verrouillage du moniteur.

Un autre point est que vous appelez waitsur Objectlui - même (vous attendez sur le moniteur d'un objet) alors que vous appelez sleeple Thread.

Pourtant , un autre point est que vous pouvez obtenir des redémarrages parasites de wait(le fil qui est en attente reprend sans raison apparente). Vous devriez toujours waitpendant la rotation à certaines conditions comme suit:

synchronized {
    while (!condition) { mon.wait(); }
}

131
Non, ça ne peut pas. Elle ne peut être interrompue.
Peter Štibraný

9
Lorsque vous interrompez, vous devez savoir quel thread vous souhaitez interrompre. Lorsque vous appelez notifier, vous avez juste besoin d'un objet, et vous ne vous souciez pas s'il y a un autre thread qui «attend» sur cet objet. wait / notify est utilisé pour la communication, tandis que sleep est utilisé pour, ehm, dormir.
Peter Štibraný

28
@Geek - pourquoi diable dites-vous que wait () gaspille les cycles CPU?
Robert Munteanu

25
L'interruption est conçue comme un mécanisme pour encourager doucement un thread à s'arrêter complètement et à annuler les opérations restantes. wait/ notifysont généralement utilisés pour attendre qu'un autre thread accomplisse une tâche, ou pour attendre qu'une certaine condition soit satisfaite.
Louis Wasserman

13
J'ai lu toutes les réponses mais je sens encore un peu d'informations manquantes. Beaucoup de gens ont écrit les définitions du Javadoc et aussi la signification des deux mots anglais mais je ne vois pas pourquoi je devrais jamais utiliser le sommeil au lieu d'attendre? Quelle est la comparaison et la différence de vitesse entre les deux? Si je peux faire tout ce que je peux faire avec le sommeil, pourquoi devrais-je choisir de dormir?
Balazs Zsoldos

334

Une différence clé non encore mentionnée est que pendant le sommeil, un thread ne libère pas les verrous qu'il détient, tandis que l'attente libère le verrou sur l'objet wait()appelé.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

105
L'attente ne libère que le verrou de l'objet que vous appelez wait (). Il ne libère aucun autre verrou.
Jon Skeet

16
En fait, vous n'avez pas besoin d'appeler sleep depuis une serrure - les verrous et l'attente / notification vont de pair, mais les verrous et le sommeil ne sont pas liés.
oxbow_lakes le

7
@oxbow_lakes - Je dirais que vous ne devriez pas dormir avec des verrous, il y a peu de cas d'utilisation pour cela. Je voulais juste souligner les différences.
Robert Munteanu

5
@RobertMunteanu, Votre réponse prétend à tort que sleepdétient les verrous java , mais ce n'est pas le cas. Pour avoir une comparaison juste, nous comparerions synchronized(OUTER_LOCK){ Thread.sleep(1000); }avec synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }et nous pouvons voir que les deux instructions ne libèrent pas le OUTER_LOCK. S'il y a une différence, on peut dire que sleepne pas explicitement utiliser Java verrous, mais la question se pose sur devis « comment leur mise en œuvre varient à un niveau inférieur? » fin de citation.
Pacerier

2
@Pacerier wait()est associé à la condition du verrou le plus interne à partir duquel il est appelé, dans votre exemple de code, wait()ne peut que se libérer LOCKet non OUTER_LOCK. C'est ainsi que le moniteur Java est conçu de toute façon. Une comparaison équitable serait synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }et synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. Dans ce cas sleep(), les deux verrous seront maintenus pendant qu'ils wait()seront libérés, LOCKmais toujoursOUTER_LOCK
danze

244

J'ai trouvé ce post utile. Il met la différence entre Thread.sleep(), Thread.yield()et Object.wait()en termes humains. Citer:

Tout cela finit par arriver au planificateur du système d'exploitation, qui distribue des tranches de temps aux processus et aux threads.

sleep(n)dit "J'ai fini avec ma tranche de temps, et s'il vous plaît ne m'en donnez pas une autre pendant au moins n millisecondes." Le système d'exploitation n'essaie même pas de planifier le thread en veille jusqu'à ce que le temps demandé soit écoulé.

yield()dit "J'ai fini avec ma tranche de temps, mais j'ai encore du travail à faire." Le système d'exploitation est libre de donner immédiatement au thread une autre tranche de temps, ou de donner un autre thread ou de traiter le processeur que le thread cédant vient d'abandonner.

wait()dit «J'ai fini avec ma tranche de temps. Ne me donnez pas une autre tranche de temps jusqu'à ce que quelqu'un appelle (). » Comme avec sleep(), le système d'exploitation n'essaiera même pas de planifier votre tâche à moins que quelqu'un n'appelle notify()(ou l'un des quelques autres scénarios de réveil se produit).

Les threads perdent également le reste de leur tranche de temps lorsqu'ils effectuent le blocage des E / S et dans quelques autres circonstances. Si un thread fonctionne sur l'intégralité de la tranche de temps, le système d'exploitation prend à peu près le contrôle comme s'il yield()avait été appelé, afin que d'autres processus puissent s'exécuter.

Vous en avez rarement besoin yield(), mais si vous avez une application lourde en calcul avec des limites de tâches logiques, l'insertion d'un yield() pourrait améliorer la réactivité du système (au détriment du temps - les changements de contexte, même uniquement vers le système d'exploitation et inversement, ne sont pas gratuits). Mesurez et testez par rapport aux objectifs qui vous tiennent à cœur, comme toujours.


Le rendement dépend essentiellement de la plate-forme ... javamex.com/tutorials/threads/yield.shtml
Pacerier

l'explication de sleep(n)signifie implicitement que le thread en cours d'exécution abandonne volontairement le moniteur du verrou, ce qui n'est pas vrai . Citation du javadoc de Thread : "Le thread ne perd la propriété d'aucun moniteur."
Clint Eastwood

2
@Jonathan il n'y a aucune mention de moniteurs dans la réponse, et c'est parce qu'il sleepn'a pas de comportement spécial concernant le moniteur que tout autre appel de méthode Java, c'est-à-dire qu'il ne les interagit pas ou ne les modifie en aucune façon. Si vous voulez dire quelque chose à propos des moniteurs, vous devez spécifier que wait, en plus des éléments mentionnés ci-dessus, vous abandonnerez temporairement le verrou sur l'objet auquel il est appelé.
pqnet

Comment fonctionne la notification au niveau du planificateur du système d'exploitation? Notification appelle-t-elle une sorte de gestionnaire d'événements avec un ID de thread particulier, permettant au planificateur de remettre le thread approprié dans la file d'attente en cours d'exécution? J'ai aussi une autre question, où se situe le concept de spinlock? Serait-ce seulement pertinent pour le sommeil ou attend-il d'utiliser le spinlock au niveau très bas?
CMCDragonkai

@Erich, utilisez wait(n)pour comparer avec sleep(n). Il n'y a aucun sens à comparer en utilisant celui sans argument.
Pacerier

68

Il y a beaucoup de réponses ici mais je n'ai trouvé la distinction sémantique mentionnée sur aucune.

Il ne s'agit pas du fil lui-même; les deux méthodes sont nécessaires car elles prennent en charge des cas d'utilisation très différents.

sleep()envoie le thread en veille comme il l'était auparavant, il ne fait que compresser le contexte et arrête de s'exécuter pendant une durée prédéfinie. Donc, pour le réveiller avant l'heure prévue, vous devez connaître la référence Thread. Ce n'est pas une situation courante dans un environnement multithread. Il est principalement utilisé pour la synchronisation de l'heure (par exemple, réveil en 3,5 secondes exactement) et / ou l'équité codée en dur (il suffit de dormir pendant un certain temps et de laisser les autres threads fonctionner).

wait(), au contraire, est un mécanisme de synchronisation de thread (ou de message) qui vous permet de notifier un Thread dont vous n'avez aucune référence stockée (ni attention). Vous pouvez le considérer comme un modèle de publication-abonnement ( wait== abonnement et notify()== publication). Fondamentalement, en utilisant notify (), vous envoyez un message (qui pourrait même ne pas être reçu du tout et normalement vous ne vous en souciez pas).

Pour résumer, vous utilisez normalement la sleep()synchronisation temporelle et la synchronisation wait()multi-thread.

Ils pouvaient être implémentés de la même manière dans le système d'exploitation sous-jacent, ou pas du tout (car les versions précédentes de Java n'avaient pas de véritable multithreading; probablement certaines petites machines virtuelles ne le font pas non plus). N'oubliez pas que Java s'exécute sur une VM, donc votre code sera transformé en quelque chose de différent en fonction de la VM / OS / HW sur laquelle il s'exécute.


54

Ici, j'ai énuméré quelques différences importantes entre les méthodes wait()et sleep().
PS: Cliquez également sur les liens pour voir le code de la bibliothèque (fonctionnement interne, il suffit de jouer un peu pour une meilleure compréhension).

attendre()

  1. wait() libère le verrou.
  2. wait()est la méthode de Objectclasse.
  3. wait() est la méthode non statique - public final void wait() throws InterruptedException { //...}
  4. wait()doivent être notifiés par notify()ou notifyAll()méthodes.
  5. wait() La méthode doit être appelée à partir d'une boucle afin de traiter les fausses alarmes.

  6. wait() La méthode doit être appelée à partir d'un contexte synchronisé (c'est-à-dire une méthode synchronisée ou un bloc), sinon elle lancera IllegalMonitorStateException

dormir()

  1. sleep() ne libère pas le verrou.
  2. sleep()est la méthode de java.lang.Threadclasse.
  3. sleep() est la méthode statique - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. après la durée spécifiée, sleep()est terminée.
  5. sleep()mieux ne pas appeler depuis la boucle (c'est -à- dire voir le code ci-dessous ).
  6. sleep()peut être appelé de n'importe où. il n'y a pas d'exigence spécifique.

Réf: Différence entre attente et sommeil

Extrait de code pour appeler la méthode wait et sleep

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

transition de thread vers différents états de thread


Est-il exact qu'un thread endormi peut être réveillé par des appels à notify ()? Certains des autres messages ici semblent impliquer qu'un fil de veille ne peut pas être réveillé mais interrompu.
berimbolo

Oui, Thread.sleep()est utilisé pour rendre le temps processeur disponible pour les autres threads. la période de sommeil peut être interrompue par des interruptions (c'est-à-dire par JVM). Lisez ce stackoverflow.com/questions/4264355/…
roottraveller

Ce post dit également que interruption () est ce qui réveille un fil endormi? Je faisais référence au diagramme d'état des threads que vous avez publié, où il est indiqué notifier ou notifier. Ramenez un thread en veille (pas en attente) à prêt à fonctionner. Je veux juste m'assurer de bien comprendre cela.
berimbolo

@berimbolo notify()ou notifyAll()sont Objectdes méthodes de classe. par conséquent, ils sont disponibles obj de toutes les classes (c'est-à-dire ici avec Threadclasse aussi). voir le code grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

2
OK, je dois en savoir plus sur la planification des threads car je ne trouve pas d'exemples de notification () ou de notification (tous) de réveil des threads en veille interrompant uniquement (). Tous les exemples associent notify () et notifyAll () aux threads en attente sur un objet moniteur.
berimbolo

29

Il y a quelques notes clés de différence que je conclus après avoir travaillé sur l'attente et le sommeil, jetez d'abord un coup d'œil sur l'échantillon en utilisant wait () et sleep ():

Exemple 1 : en utilisant wait () et sleep ():

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

Laissez la clarté quelques notes clés:

  1. Appelez :
    • wait (): Appel sur le thread actuel qui contient l'objet HandObject
    • sleep (): Appelez la tâche d'exécution du thread pour obtenir de la bière (la méthode de classe affecte donc le thread en cours d'exécution)
  2. Synchronisé :
    • wait (): lorsque plusieurs threads synchronisés accèdent au même objet (HandObject) (Lorsque vous avez besoin d'une communication entre plusieurs threads (thread exécuter le codage, thread exécuter obtenir de la bière) accès sur le même objet HandObject)
    • sleep (): lorsque la condition d'attente pour continuer à s'exécuter (bière en attente disponible)
  3. Maintenez le verrou :
    • wait (): relâchez le verrou pour que d'autres objets aient la chance de s'exécuter (HandObject est gratuit, vous pouvez faire un autre travail)
    • sleep (): garder le verrou pendant au moins t fois (ou jusqu'à l'interruption) (Mon travail n'est toujours pas terminé, je continue à maintenir le verrou et j'attends une condition pour continuer)
  4. Condition de réveil :
    • wait (): jusqu'à ce que l'appel notifie (), notifyAll () de l'objet
    • sleep (): jusqu'à expiration au moins du temps ou interruption de l'appel
  5. Et le dernier point est à utiliser quand, comme l' estani l' indique:

vous utilisez normalement sleep () pour la synchronisation horaire et wait () pour la synchronisation multi-thread.

Corrigez-moi si j'ai tort, s'il-vous plait.


26

Différence entre wait () et sleep ()

  • La différence fondamentale est que wait()provient Objectet sleep()est une méthode statique Thread.

  • La principale différence est que wait()le sleep()déverrouillage ne libère aucun verrou en attendant.

  • wait()est utilisé pour la communication inter-thread tandis que sleep()est utilisé pour introduire une pause sur l'exécution, en général.

  • wait()devrait être appelé depuis synchroniser à l'intérieur ou bien nous obtenons un IllegalMonitorStateException, tandis que sleep() peut être appelé n'importe où.

  • Pour relancer un fil depuis wait(), vous devez appeler notify()ou notifyAll(). Quant sleep(),au thread, il démarre après un intervalle de temps spécifié.

Similitudes

  • Les deux font passer le thread en cours dans l' état Non exécutable .
  • Les deux sont des méthodes natives .

18

C'est une question très simple, car ces deux méthodes ont une utilisation totalement différente.

La principale différence est d'attendre pour libérer le verrou ou le moniteur pendant que le sommeil ne libère aucun verrou ou moniteur pendant l'attente. Wait est utilisé pour la communication entre les threads tandis que sleep est utilisé pour introduire une pause lors de l'exécution.

Ce n'était qu'une explication claire et basique, si vous voulez plus que cela, continuez à lire.

En cas de wait()thread de méthode en attente et il ne reviendra pas automatiquement jusqu'à ce que nous appelions la notify()méthode (ou notifyAll()si vous avez plus d'un thread en attente et que vous souhaitez réveiller tous ces threads). Et vous avez besoin synchronisé ou verrouillage de l' objet ou le verrouillage de classe pour accéder au wait()ou notify()ou notifyAll()méthodes. Et encore une chose, la wait()méthode est utilisée pour la communication entre les threads, car si un thread passe en attente, vous aurez besoin d'un autre thread pour le réveiller.

Mais dans ce cas, sleep()c'est une méthode qui est utilisée pour maintenir le processus pendant quelques secondes ou le temps que vous voulez. Parce que vous n'avez pas besoin de provoquer une notify()ou notifyAll()méthode pour obtenir ce retour de fil. Ou vous n'avez besoin d'aucun autre fil pour rappeler ce fil. Comme si vous voulez que quelque chose se produise après quelques secondes, comme dans un jeu après le tour de l'utilisateur, vous voulez que l'utilisateur attende que l'ordinateur joue, alors vous pouvez mentionner la sleep()méthode.

Et une autre différence importante qui est souvent demandée lors des entretiens: sleep()appartient à la Threadclasse et wait()appartient à la Objectclasse.

Ce sont toutes les différences entre sleep()et wait().

Et il existe une similitude entre les deux méthodes: elles sont toutes deux vérifiées, vous devez donc essayer catch ou throw pour accéder à ces méthodes.

J'espère que cela t'aidera.


16

source: http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()envoie le thread actuel à l'état "Non exécutable" pendant un certain temps. Le thread conserve les moniteurs qu'il a acquis - c'est-à-dire si le thread est actuellement dans un bloc ou une méthode synchronisée, aucun autre thread ne peut entrer dans ce bloc ou cette méthode. Si un autre thread appelle, t.interrupt()il réveillera le thread endormi.

Notez que sleep est une méthode statique, ce qui signifie qu'elle affecte toujours le thread actuel (celui qui exécute la méthode sleep). Une erreur courante consiste à appeler t.sleep()où t est un thread différent; même alors, c'est le thread actuel qui dormira, pas le thread t.

t.suspend()est obsolète. Son utilisation permet d'arrêter un thread autre que le thread actuel. Un thread suspendu conserve tous ses moniteurs et comme cet état n'est pas interruptible, il est sujet à un blocage.

object.wait()envoie le thread actuel dans l'état "Not Runnable" , comme sleep(), mais avec une torsion. L'attente est appelée sur un objet, pas sur un thread; nous appelons cet objet «l'objet verrouillé». Avant que lock.wait()soit appelé, le thread actuel doit se synchroniser sur l'objet de verrouillage; wait() libère ensuite ce verrou et ajoute le fil à la "liste d'attente" associée au verrou. Plus tard, un autre thread peut se synchroniser sur le même objet de verrouillage et appeler lock.notify(). Cela réveille le fil d'origine en attente. Fondamentalement, wait()/ notify()est similaire à sleep()/ interrupt(), seul le thread actif n'a pas besoin d'un pointeur direct vers le thread endormi, mais uniquement vers l'objet de verrouillage partagé.


14

Attendre et dormir sont deux choses différentes:

  • Dans sleep()le thread cesse de fonctionner pendant la durée spécifiée.
  • Dans wait()le thread cesse de fonctionner jusqu'à ce que l'objet attendu soit notifié, généralement par d'autres threads.

mais vous pouvez interrompre un fil endormi. Dans ce cas, wait () est redondant en fait, il gaspille aussi les cycles CPU :-(
Geek

9
L'attente ne gaspille pas les cycles CPU.
Peter Štibraný

1
@Peter - Je pense que oui. Il attend () son bloc de cycles CPU puis le système d'exploitation donne les cycles CPU à d'autres Threads. Je pense que cela pourrait dépendre du système d'exploitation, je ne suis pas sûr.
Geek

3
Ce serait une très mauvaise implémentation de wait () si cela gaspillait les cycles CPU. wait / notify est beaucoup utilisé pour la communication entre les fils.
Peter Štibraný

2
@Pacerier les deux constructions sont destinées à un usage différent. Si vous voulez qu'un thread s'arrête pendant une durée fixe que vous utilisez sleep, si vous voulez qu'il s'arrête jusqu'à ce que certaines entrées proviennent de l'autre que vous utilisez wait/ notify. interruptest conçu comme un moyen de signaler à un thread qu'il doit arrêter de faire ce qu'il fait et se terminer. Il est géré par sleep, waitmais bloque également les fonctions d'E / S (et vous pouvez implémenter des fonctions avec le même comportement en appelant la méthode Thread.interrupted()). En ce qui concerne les performances, les fonctions sont généralement optimisées pour l'objectif pour lequel elles ont été conçues.
pqnet

11

sleepest une méthode de Thread, waitest une méthode de Object, wait/notifyest donc une technique de synchronisation des données partagées en Java (en utilisant le moniteur ), mais sleepest une méthode simple de thread pour se mettre en pause.


8

sleep () est une méthode qui est utilisée pour maintenir le processus pendant quelques secondes ou le temps que vous vouliez mais en cas de thread de méthode wait () passe en état d'attente et il ne reviendra pas automatiquement jusqu'à ce que nous appelons le notify () ou notifyAll ().

La principale différence est que wait () libère le verrou ou le moniteur pendant que sleep () ne libère aucun verrou ou moniteur pendant l'attente. Wait est utilisé pour la communication entre les threads tandis que sleep est utilisé pour introduire une pause lors de l'exécution, en général.

Thread.sleep () envoie le thread actuel à l'état "Not Runnable" pendant un certain temps. Le thread conserve les moniteurs qu'il a acquis - c'est-à-dire que si le thread est actuellement dans un bloc ou une méthode synchronisée, aucun autre thread ne peut entrer dans ce bloc ou cette méthode. Si un autre thread appelle t.interrupt (), il réveillera le thread en veille. Notez que sleep est une méthode statique, ce qui signifie qu'elle affecte toujours le thread actuel (celui qui exécute la méthode sleep). Une erreur courante consiste à appeler t.sleep () où t est un thread différent; même alors, c'est le thread actuel qui dormira, pas le thread t.

object.wait () envoie le thread actuel dans l'état "Not Runnable", comme sleep (), mais avec une torsion. L'attente est appelée sur un objet, pas sur un thread; nous appelons cet objet «l'objet verrouillé». Avant d'appeler lock.wait (), le thread actuel doit se synchroniser sur l'objet lock; wait () libère alors ce verrou et ajoute le fil à la «liste d'attente» associée au verrou. Plus tard, un autre thread peut se synchroniser sur le même objet de verrouillage et appeler lock.notify (). Cela réveille le fil d'origine en attente. Fondamentalement, wait () / notify () est comme sleep () / interrupt (), seul le thread actif n'a pas besoin d'un pointeur direct vers le thread endormi, mais uniquement vers l'objet de verrouillage partagé.

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}

Classons tous les points ci-dessus:

Call on:

  • wait (): appeler un objet; le thread actuel doit se synchroniser sur l'objet de verrouillage.
  • sleep (): Appel sur un fil; toujours en cours d'exécution du thread.

Synchronized:

  • wait (): lorsque plusieurs threads synchronisés accèdent au même objet un par un.
  • sleep (): lors de la synchronisation de plusieurs threads, attendez la mise en veille du thread en veille.

Hold lock:

  • wait (): relâchez le verrou pour que d'autres objets aient la chance de s'exécuter.
  • sleep (): garder le verrouillage pendant au moins t fois si le délai d'attente est spécifié ou si quelqu'un l'interrompt.

Wake-up condition:

  • wait (): jusqu'à ce que l'appel notifie (), notifyAll () de l'objet
  • sleep (): jusqu'à expiration au moins du temps ou interruption d'appel ().

Usage:

  • sleep (): pour la synchronisation de l'heure et;
  • wait (): pour la synchronisation multi-thread.

Réf: diff sleepetwait


6

En termes simples, wait is wait Jusqu'à ce qu'un autre thread vous invoque alors que sleep est "don't execute next statement" pendant une période de temps spécifiée.

De plus, sleep est une méthode statique dans la classe Thread et il fonctionne sur le thread, tandis que wait () est dans la classe Object et appelé sur un objet.

Un autre point, lorsque vous appelez wait sur un objet, le thread impliqué synchronise l'objet, puis attend. :)


1
Pourquoi avez-vous besoin des deux? Pourquoi sleep () n'est pas suffisant?
Geek

2
Notify est utilisé pour la communication entre les threads. Pour appeler wait, vous avez besoin d'un objet, synchronisez dessus, puis appelez wait dessus. Pour être averti, vous avez besoin d'un autre thread pour synchroniser sur le même objet, et appelez notify.
Peter Štibraný

6

waitet les sleepméthodes sont très différentes:

  • sleep n'a aucun moyen de "se réveiller",
  • alors qu'il waita un moyen de "se réveiller" pendant la période d'attente, par un autre thread appelant notifyou notifyAll.

À bien y penser, les noms prêtent à confusion à cet égard; sleepest cependant un nom standard et waitressemble à WaitForSingleObjectou WaitForMultipleObjectsdans l'API Win.


3
Mais nous pouvons interrompre un sommeil non? alors quelle est la différence avec ce sommeil / interruption vs attente / notification?
Pacerier

2
Vous pouvez interrompre une personne endormie, mais vous ne pouvez en informer qu'une personne en attente. Les fils sont les mêmes.
Rishi

5

De cet article: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

Méthode wait ().

1) Le thread qui appelle la méthode wait () libère le verrou qu'il détient.

2) Le thread retrouve le verrou après que d'autres threads ont appelé les méthodes notify () ou notifyAll () sur le même verrou.

3) la méthode wait () doit être appelée dans le bloc synchronisé.

4) La méthode wait () est toujours appelée sur les objets.

5) Les threads en attente peuvent être réveillés par d'autres threads en appelant les méthodes notify () ou notifyAll ().

6) Pour appeler la méthode wait (), le thread doit avoir un verrou d'objet.

sleep (), méthode

1) Le thread qui appelle la méthode sleep () ne libère pas le verrou qu'il détient.

2) la méthode sleep () peut être appelée à l'intérieur ou à l'extérieur du bloc synchronisé.

3) La méthode sleep () est toujours appelée sur les threads.

4) Les fils dormants ne peuvent pas être réveillés par d'autres fils. Si c'est le cas, le thread lèvera InterruptedException.

5) Pour appeler la méthode sleep (), le thread n'a pas besoin d'avoir le verrouillage d'objet.


4

Ici, wait () sera dans l'état d'attente jusqu'à ce qu'il le notifie par un autre thread, mais où sleep () aura un certain temps..après cela, il passera automatiquement à l'état Ready ...


4
  1. wait()est une méthode de Objectclasse.
    sleep()est une méthode de Threadclasse.

  2. sleep()permet au thread de passer à l' sleepétat pendant x millisecondes.
    Lorsqu'un fil se met en veille it doesn’t release the lock.

  3. wait()permet au fil de libérer le verrou et goes to suspended state.
    Ce thread sera actif lorsqu'une méthode notify()or notifAll()sera appelée pour le même objet.


4

Une grande différence potentielle entre sommeil / interruption et attente / notification est que

Générer une exception lorsqu'elle n'est pas nécessaire est inefficace. Si vous avez des threads qui communiquent entre eux à un taux élevé, cela générerait de nombreuses exceptions si vous appeliez constamment interruption, ce qui est un gaspillage total de CPU.


+1, Un point valide en fait, bien que discuter sur les internes des implémentations peut être plus pertinent pour l'analyse des performances ...
Pacerier

En d'autres termes, les frais généraux liés à la création d'exceptions peuvent être considérablement inférieurs à ceux de la mise en œuvre du système de l'un par rapport à l'autre.
Pacerier

3

Vous avez raison - Sleep () fait que ce thread se "met en veille" et le CPU s'éteint et traite les autres threads (autrement connu sous le nom de changement de contexte) alors que je pense que Wait attend que le CPU traite le thread actuel.

Nous avons les deux parce que même si cela peut sembler judicieux de laisser d'autres personnes utiliser le processeur pendant que vous ne l'utilisez pas, en réalité, il y a un surcoût pour le changement de contexte - selon la durée du sommeil, il peut être plus cher dans les cycles du processeur pour changer de threads que pour simplement avoir votre thread ne rien faire pendant quelques ms.

Notez également que le sommeil force un changement de contexte.

De plus - en général, il n'est pas possible de contrôler le changement de contexte - pendant l'attente, le système d'exploitation peut (et va attendre plus longtemps) choisir de traiter d'autres threads.


4
wait () ne garde pas le CPU traiter le thread courant. C'est comme le sommeil car il provoque également un changement de contexte: javamex.com/tutorials/threads/context_switch.shtml . Je demande depuis six mois tout autour de stackoverflow et il semble que personne ne sache quelle est la différence entre attente / notification et veille / interruption.
Pacerier

bien que le sommeil ne garde pas le CPU dans le traitement du thread actuel, je pense que c'est quand même un peu un fardeau pour le CPU, car le CPU a besoin de suivre le moment où mettre fin au sommeil. Il n'a pas ce déclencheur externe comme "notifier" en attente. Non?
Vladimir Nabokov

@VladimirNabokov, Le déclencheur externe est interrupt. L'heure de fin est nen wait(n). ¶¶ Cela fait maintenant 8 ans et personne n'a encore la réponse!
Pacerier

3

Les méthodes sont utilisées pour différentes choses.

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.sleep (n) peut être interrompu, mais Object.wait () doit être notifié. Il est possible de spécifier le temps maximum à attendre: Object.wait(5000)il serait donc possible d'utiliser waitpour, euh, sleepmais alors vous devez vous soucier des verrous.

Aucune des méthodes n'utilise le processeur pendant le sommeil / l'attente.

Les méthodes sont implémentées en utilisant du code natif, en utilisant des constructions similaires mais pas de la même manière.

Cherchez par vous-même: le code source des méthodes natives est-il disponible? Le fichier /src/share/vm/prims/jvm.cppest le point de départ ...


La synchronisation Thread.sleep peut également être définie sur indéfinie. Le timing Object.wait peut également être défini sur défini. Cette réponse n'explique pas pourquoi nous avons besoin de 2 marteaux qui font la même chose.
Pacerier

Thread.sleep(big_num) doit être interrompu. Object.wait(small_num) peut être notifié.
Pacerier

3

Attendre () et dormir () Différences?

Thread.sleep () Une fois son travail terminé, il ne reste plus qu'à libérer le verrou à tout le monde. jusqu'à ce que cela ne libère jamais le verrou à personne.

  Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

Object.wait () Lorsqu'il passera à l'étape d'attente, il relâchera la clé et attendra quelques secondes en fonction du paramètre.

Par exemple:

vous prenez le café dans la main droite, vous pouvez prendre un autre personne de la même main, quand allez-vous déposer puis ne prendre qu'un autre objet du même type ici. aussi. c'est le sommeil () vous dormez, vous n'avez pas travaillé, vous ne faites que dormir .. même ici aussi.

attendre(). quand vous êtes abattu et prenez un autre moyen pendant que vous attendez, c'est attendre

vous jouez un film ou quoi que ce soit dans votre système de la même manière que le joueur, vous ne pouvez pas en jouer plus d'un à la fois, c'est ici, lorsque vous fermez et choisissez un autre film ou chanson de quelqu'un pendant que s'appelle attendre


3

waitlibère le verrou et sleepne le fait pas. Un fil dans l' état d' attente est admissible à se réveiller dès notifyou notifyAllest appelé. Mais dans le cas où sleeple fil garde le verrou et il ne sera éligible qu'une fois le temps de sommeil terminé.


Donc, si le thread dort pendant 10 secondes et qu'une exception interrompue se produit ????
Geek

@Geek An InterruptedExceptionest lancé, comme il est dit dans le Javadoc.
Marquis de Lorne

@EJP: Êtes-vous le même EJP qui était sur les forums sun.java.com? Au moins votre score suggère la même chose :-)
Geek

2

sleep()fait en sorte que le thread en cours passe de l'état d'exécution à l'état de blocage pendant une durée spécifiée. Si le thread actuel a le verrou de n'importe quel objet, il continue à le maintenir, ce qui signifie que les autres threads ne peuvent exécuter aucune méthode synchronisée dans cet objet de classe.

wait() La méthode fait que le thread actuel entre dans l'état de bloc pendant une durée spécifiée ou jusqu'à notification, mais dans ce cas, le thread libère le verrou de l'objet (ce qui signifie que d'autres threads peuvent exécuter toutes les méthodes synchronisées de l'objet appelant.


2

À mon avis, la principale différence entre les deux mécanismes est que le mode veille / interruption est le moyen le plus élémentaire de gérer les threads, tandis que l' attente / notification est une abstraction visant à faciliter l'intercommunication des threads.Cela signifie que le sommeil / interruption peut tout faire, mais que cette tâche spécifique est plus difficile à faire.

Pourquoi attendre / notifier est-il plus approprié? Voici quelques considérations personnelles:

  1. Il impose la centralisation. Il permet de coordonner la communication entre un groupe de threads avec un seul objet partagé. Cela simplifie beaucoup le travail.

  2. Il applique la synchronisation. Parce que le programmeur encapsule l'appel pour attendre / notifier dans un bloc synchronisé.

  3. Il est indépendant de l'origine et du numéro du fil. Avec cette approche, vous pouvez ajouter plus de fils arbitrairement sans modifier les autres fils ou garder une trace de ceux existants. Si vous avez utilisé sleep / interruption, vous devez d'abord conserver les références aux threads en veille, puis les interrompre une par une, à la main.

Un exemple de la vie réelle qui est bon d'expliquer c'est un restaurant classique et la méthode que le personnel utilise pour communiquer entre eux: Les serveurs laissent les demandes des clients dans un endroit central (une planche de liège, une table, etc.), sonner la cloche, et les ouvriers de la cuisine viennent prendre ces demandes. Une fois qu'un cours est prêt, le personnel de cuisine sonne à nouveau pour que les serveurs soient au courant et les amènent aux clients.


2

Un exemple de sommeil ne libère pas le verrou et

Ici, il y a deux classes:

  1. Main : contient la méthode principale et deux threads.
  2. Singleton : il s'agit de la classe singleton avec deux méthodes statiques getInstance () et getInstance (boolean isWait).

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

et

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

Maintenant, exécutez cet exemple, vous obtiendrez ci-dessous la sortie:

_instance :null
Both singleton are same

Ici, les instances Singleton créées par threadA et threadB sont identiques. Cela signifie que le threadB attend à l'extérieur jusqu'à ce que le threadA libère son verrou.

Maintenant, changez Singleton.java en commentant Thread.sleep (500); méthode et décommentation Singleton.class.wait (500); . Ici à cause de Singleton.class.wait (500); La méthode threadA libérera tous les verrous d'acquisition et passera à l'état «Non exécutable», threadB obtiendra la modification à entrer dans le bloc synchronisé.

Maintenant, exécutez à nouveau:

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

Ici, les instances Singleton créées par threadA et threadB ne sont PAS les mêmes car threadB a obtenu une modification pour entrer dans le bloc synchronisé et après 500 millisecondes, threadA a démarré à partir de sa dernière position et a créé un autre objet Singleton.


2

Doit être appelée à partir du bloc synchronisé: la wait() méthode est toujours appelée à partir du bloc synchronisé, c'est-à-dire que la wait()méthode doit verrouiller le moniteur d'objet avant l'objet sur lequel elle est appelée. Mais la sleep()méthode peut être appelée depuis un bloc synchronisé externe, c'est-à-dire qu'elle sleep()n'a pas besoin de moniteur d'objet.

IllegalMonitorStateException: si la wait()méthode est appelée sans acquérir le verrou d'objet, elle IllegalMonitorStateExceptionest levée lors de l'exécution, maissleep() méthode ne lève jamais une telle exception.

Appartient à quelle classe: la wait() méthode appartient à la java.lang.Objectclasse mais la sleep()méthode appartient à la java.lang.Threadclasse.

Appelé sur un objet ou un thread: la wait() méthode est appelée sur les objets mais la sleep()méthode est appelée sur les threads et non sur les objets.

État du thread: lorsque la wait()méthode est appelée sur l'objet, le thread qui contenait le moniteur de l'objet passe de l'état d'exécution à l'état d'attente et ne peut revenir à l'état d'exécution que lorsque la méthode notify()ou notifyAll()est appelée sur cet objet. Et plus tard, le planificateur de threads planifie ce thread de passer de exécutable à l'état en cours d'exécution. quand sleep()est appelé sur le thread, il passe de l'état d'exécution à l'état d'attente et peut revenir à l'état d'exécution lorsque le temps de veille est écoulé.

En cas d'appel depuis un bloc synchronisé: lorsque la wait()méthode est appelée, le thread quitte le verrou de l'objet. Mais la sleep()méthode lorsqu'elle est appelée à partir d'un bloc synchronisé ou d'un thread de méthode ne laisse pas le verrou d'objet.

Pour plus de référence


probablement une meilleure URL de référence que celle-ci.
Drew

2

Depuis la page de documentation d'Oracle sur la méthode wait () de Object:

public final void wait()
  1. Force le thread actuel à attendre qu'un autre thread appelle la notify()méthode ou la notifyAll()méthode pour cet objet. En d'autres termes, cette méthode se comporte exactement comme si elle exécutait simplement l'appel wait(0).
  2. Le thread actuel doit posséder le moniteur de cet objet. Le thread libère la propriété de ce moniteur et attend qu'un autre thread notifie aux threads en attente de réveil sur le moniteur de cet objet
  3. des interruptions et des réveils parasites sont possibles
  4. Cette méthode ne doit être appelée que par un thread propriétaire du moniteur de cet objet

Cette méthode jette

  1. IllegalMonitorStateException - si le thread actuel n'est pas le propriétaire du moniteur de l'objet.

  2. InterruptedException- si un thread a interrompu le thread actuel avant ou pendant que le thread actuel attendait une notification. Le statut interrompu du thread actuel est effacé lorsque cette exception est levée.

Depuis la page de documentation d'Oracle sur la méthode de Threadclasse sleep () :

public static void sleep(long millis)
  1. Provoque la mise en veille du thread en cours d'exécution (arrête temporairement l'exécution) pendant le nombre de millisecondes spécifié, sous réserve de la précision et de l'exactitude des temporisateurs et des planificateurs du système.
  2. Le thread ne perd la propriété d'aucun moniteur.

Cette méthode lance:

  1. IllegalArgumentException - si la valeur de millis est négative

  2. InterruptedException- si un thread a interrompu le thread actuel. Le statut interrompu du thread actuel est effacé lorsque cette exception est levée.

Autre différence clé:

wait()est une méthode non statique (méthode d'instance) contrairement à la méthode statique sleep()(méthode de classe).


1

wait()est donné à l'intérieur d'une méthode synchronisée alors qu'il sleep()est donné à l'intérieur d'une méthode non synchronisée car la wait()méthode libère le verrou sur l'objet mais sleep()ou yield()libère le lock().


sleep()peut être à l'intérieur d'un synchronizedbloc ou d'une méthode. La réponse n'explique rien.
Marquis de Lorne

1
  • La méthode wait(1000)fait dormir le thread actuel jusqu'à une seconde .
    • Un thread peut dormir moins de 1 seconde s'il reçoit l' appel de méthode notify()ornotifyAll() .
  • L'appel à sleep(1000)provoque la mise en veille du thread actuel pendant exactement 1 seconde .
    • De plus, le fil dormant ne maintient pas le verrouillage d'une ressource . Mais le fil d'attente le fait.

1
sleep(1000)ne garantit pas de dormir pendant exactement 1 seconde. Il peut être interrompu auparavant.
Lucio

1
Ces messages sont tellement déroutants. Tous les autres messages sur ce fil disent qu'un fil endormi détient le verrou et qu'un fil en attente NE tient PAS le verrou. De même, la publication avec le diagramme implique que les appels à notify () réveillent les threads en veille, mais d'autres publications (et les diagrammes d'état des threads) impliquent que seule interruption () ou le délai d'expiration passant le font. Je viens de me commander une copie de la concurrence Java dans la pratique, quelque chose que j'aurais dû lire il y a longtemps!
berimbolo

1

En fait, tout cela est clairement décrit dans les documents Java (mais je ne l'ai réalisé qu'après avoir lu les réponses).

http://docs.oracle.com/javase/8/docs/api/index.html :

wait () - Le thread actuel doit posséder le moniteur de cet objet. Le thread libère la propriété de ce moniteur et attend qu'un autre thread notifie aux threads en attente sur le moniteur de cet objet de se réveiller via un appel à la méthode notify ou à la méthode notifyAll. Le thread attend ensuite jusqu'à ce qu'il puisse récupérer la propriété du moniteur et reprendre l'exécution.

sleep () - Fait dormir le thread en cours d'exécution (arrête temporairement l'exécution) pendant le nombre de millisecondes spécifié, sous réserve de la précision et de l'exactitude des temporisateurs et des planificateurs du système. Le thread ne perd la propriété d'aucun moniteur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.