Quelle est la différence entre wait()
et sleep()
dans les threads?
Est-ce que je comprends qu'un thread wait()
ing est toujours en mode de fonctionnement et utilise des cycles de processeur, mais qu'un sleep()
ing ne consomme aucun cycle de processeur correct?
Pourquoi avons-nous les deuxwait()
et sleep()
: comment leur mise en œuvre varie-t-elle à un niveau inférieur?
Un wait
peut être "réveillé" par un autre thread appelant notify
sur le moniteur en attente alors qu'un sleep
ne le peut pas. De plus, un wait
(et notify
) doit apparaître dans un bloc synchronized
sur l'objet moniteur alors que sleep
ne le fait pas:
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 objet mon
) et le premier thread (en supposant que ce soit le seul thread en attente sur le moniteur) se réveillera.
Vous pouvez également appeler notifyAll
si plusieurs threads attendent sur le moniteur - cela réveillera tous . Cependant, un seul des threads pourra saisir le moniteur (rappelez-vous que le wait
est dans un bloc synchronized
) et continuer: les autres seront alors bloqués jusqu'à ce qu'ils puissent obtenir le verrou du moniteur.
Un autre point est que vous appelez wait
sur Object
lui-même (c'est-à-dire que vous attendez sur le moniteur d'un objet) alors que vous appelez sleep
sur Thread
.
Encore un autre point est que vous pouvez obtenir des réveils parasites de wait
(c’est-à-dire que le fil en attente reprend sans raison apparente). Vous devriez toujours wait
tout en tournant sur une condition comme suit:
synchronized {
while (!condition) { mon.wait(); }
}
Une différence clé qui n’a pas encore été mentionnée est que, tout en étant en veille, un thread libère pas les verrous qu’il détient, tandis que l’attente libère le verrou sur l’objet sur lequel wait()
est appelé.
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
J'ai trouvé ce post utile. Cela fait la différence entre Thread.sleep()
, Thread.yield()
et Object.wait()
en termes humains. Citer:
Tout se résume finalement au planificateur du système d’exploitation, qui distribue des tranches de temps aux processus et aux threads.
sleep(n)
dit "J'ai fini ma tranche de temps et s'il vous plaît, n'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 tant que le temps demandé n'est pas écoulé.
yield()
dit "J'ai terminé mon 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, le thread cédant venant d'être abandonné.
wait()
dit "J'ai fini avec mon laps de temps. Ne me donnez pas un autre intervalle de temps jusqu'à ce que quelqu'un appelle notify (). ” Comme avecsleep()
, le système d'exploitation n'essayera même pas de planifier votre tâche, sauf si appellenotify()
(ou l'un des quelques scénarios de réveil qui se produisent).Les fils perdent également le reste de leur tranche de temps lorsqu'ils bloquent IO et dans quelques autres circonstances. Si un thread fonctionne sur toute la tranche de temps, le système d'exploitation prend le contrôle de force, comme si
yield()
avait été appelé, de sorte que d'autres processus puissent s'exécuter.Vous avez rarement besoin de
yield()
, mais si vous avez une application très lourde en calcul avec des limites logiques pour les tâches, insérer uneyield()
peut améliorer la réactivité du système (au détriment de temps - les changements de contexte, même juste pour le système d'exploitation et inversement, ne sont pas libres). Comme toujours, mesurez et testez par rapport aux objectifs qui vous tiennent à cœur.
Il y a beaucoup de réponses ici mais je n'ai pas pu trouver la distinction sémantique mentionnée dans aucune.
Ce n'est pas sur le 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 avant, il compresse simplement le contexte et cesse de s'exécuter pendant une durée prédéfinie. Donc, afin de 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 multi-thread. Il est principalement utilisé pour la synchronisation temporelle (par exemple, réveil exactement 3,5 secondes) et/ou une équité codée en dur (veillez un instant et laissez les autres threads fonctionner).
wait()
, au contraire, est un mécanisme de synchronisation de threads (ou de messages) qui vous permet de notifier un thread dont vous ne possédez aucune référence (ni aucun soin). Vous pouvez le considérer comme un modèle de publication/abonnement (wait
== subscribe et notify()
== publish). En utilisant essentiellement 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 sleep()
pour la synchronisation temporelle et wait()
pour la synchronisation multi-thread.
Ils peuvent ê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 ne comportaient pas de véritable multithreading; probablement de petites machines virtuelles ne le font pas non plus). N'oubliez pas que Java s'exécute sur une machine virtuelle. Votre code sera transformé en quelque chose de différent en fonction de la machine virtuelle/système d'exploitation/matériel sur lequel il s'exécute.
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).
wait()
libère le verrou.wait()
est la méthode de Object
class.wait()
est la méthode non statique - public final void wait() throws InterruptedException { //...}
wait()
doit être notifié par les méthodes notify()
ou notifyAll()
.La méthode wait()
doit être appelée depuis une boucle pour traiter les fausses alarmes.
La méthode wait()
doit être appelée à partir d'un contexte synchronisé (c'est-à-dire une méthode ou un bloc synchronisé), sinon elle lancera IllegalMonitorStateException
sleep()
ne libère pas le verrou.sleep()
est la méthode de Java.lang.Thread
class.sleep()
est la méthode statique - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
sleep()
est terminé.sleep()
Mieux vaut ne pas appeler depuis la boucle (c'est-à-dire , voir le code ci-dessous ).sleep()
peut être appelé de n'importe où. il n'y a pas d'exigence spécifique.Ref: Différence entre attente et sommeil
Extrait de code pour l'appel des méthodes d'attente et de veille
synchronized(monitor){
while(condition == true){
monitor.wait() //releases monitor lock
}
Thread.sleep(100); //puts current thread on Sleep
}
Il y a quelques différences entre les notes clés que je conclus après avoir travaillé sur wait et sleep, jetez d'abord un coup d'œil sur l'échantillon en utilisant wait () et sleep ():
Exemple1 : utiliser attendre () et sommeil ():
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:
vous utilisez normalement sleep () pour la synchronisation temporelle et wait () pour la synchronisation multi-thread.
Corrigez-moi si j'ai tort, s'il-vous plait.
La différence fondamentale est que wait()
provient de Object
et sleep()
est une méthode statique de Thread
.
La principale différence est que wait()
libère le verrou tandis que sleep()
ne lâche aucun verrou pendant l’attente.
wait()
est utilisé pour la communication inter-thread tandis que sleep()
est utilisé pour introduire une pause lors de l'exécution, en général.
wait()
devrait être appelé de l'intérieur à synchroniser ou nous obtenons un IllegalMonitorStateException
, alors que sleep()
peut être appelé n'importe où.
wait()
, vous devez appeler notify()
ou notifyAll()
. Comme pour sleep(),
, le thread est démarré après un intervalle de temps spécifié.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 que le verrou ou le moniteur soit libéré pendant que la mise en veille ne libère aucun verrou ni le moniteur pendant l'attente. Wait est utilisé pour la communication inter-thread tandis que le mode veille est utilisé pour introduire une pause dans l'exécution.
Ceci était juste une explication claire et basique, si vous voulez plus que cela, continuez à lire.
Dans le cas de wait()
, le thread de méthode passe en état d'attente et il ne reviendra pas automatiquement tant que nous n'aurons pas appelé la méthode notify()
(ou notifyAll()
si vous avez plus d'un thread en attente et vous voulez réveiller tous ces fils). Et vous avez besoin d'un verrou synchronisé, d'objet ou de classe pour accéder aux méthodes wait()
ou notify()
ou notifyAll()
. Et encore une chose, la méthode wait()
est utilisée pour la communication inter-thread, car si un thread passe en attente, vous aurez besoin d'un autre thread pour l'activer.
Mais dans le cas de sleep()
, il s’agit d’une méthode utilisée pour mettre en attente le processus pendant quelques secondes ou la durée souhaitée. Parce que vous n'avez pas besoin de provoquer une méthode notify()
ou notifyAll()
pour récupérer ce fil. Ou vous n'avez pas besoin d'un autre thread pour rappeler ce thread. Par exemple, si vous voulez que quelque chose se passe après quelques secondes, comme dans un jeu après le tour de l'utilisateur, vous voulez que celui-ci attende que l'ordinateur démarre, puis vous pouvez mentionner la méthode sleep()
.
Et une autre différence importante qui est souvent posée dans les entretiens: sleep()
appartient à Thread
class et wait()
appartient à Object
class.
Ce sont toutes les différences entre sleep()
et wait()
.
Et il y a une similitude entre les deux méthodes: les deux sont des instructions vérifiées, vous devez donc essayer des catch ou des jets pour accéder à ces méthodes.
J'espère que cela t'aidera.
source: http://www.jguru.com/faq/view.jsp?EID=47127
Thread.sleep()
envoie le thread en cours à 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é, aucun autre thread ne peut entrer dans ce bloc ou cette méthode. Si un autre thread appellet.interrupt()
, le thread en veille sera réactivé.Notez que le sommeil est une méthode statique, ce qui signifie qu’elle affecte toujours le thread actuel (celui qui exécute la méthode de veille). Une erreur courante consiste à appeler
t.sleep()
où t est un autre thread; même dans ce cas, c'est le thread actuel qui va dormir, pas le thread t.
t.suspend()
est obsolète. Il est possible d’arrêter un thread autre que le thread actuel. Un thread suspendu conserve tous ses moniteurs et, cet état n'étant pas interruptible, il est sujet à des blocages.
object.wait()
envoie le thread actuel dans l'état "Non exécutable" , commesleep()
, mais avec une torsion. Wait est appelé sur un objet, pas un thread; nous appelons cet objet "l'objet verrou". Avant d'appelerlock.wait()
, le thread actuel doit se synchroniser sur l'objet verrou;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 verrou et appelerlock.notify()
. Cela réveille le fil original en attente. En gros,wait()
/notify()
est semblable àsleep()
/interrupt()
, seul le thread actif n'a pas besoin d'un pointeur direct sur le thread en veille, mais uniquement sur l'objet de verrouillage partagé.
Attendre et dormir sont deux choses différentes:
sleep()
, le thread cesse de fonctionner pendant la durée spécifiée.wait()
, le thread cesse de fonctionner jusqu'à ce que l'objet à attendre soit notifié, généralement par d'autres threads.sleep
est une méthode de Thread
, wait
est une méthode de Object
, donc wait/notify
est une technique de synchronisation des données partagées dans Java. _ (using monitor ), mais sleep
est une méthode simple de thread pour se mettre en pause.
sleep () est une méthode utilisée pour mettre le processus en attente pendant quelques secondes ou l'heure désirée, mais en cas d'utilisation de la méthode wait (), le thread y passe. en attente et il ne reviendra pas automatiquement tant que nous n’aurons pas appelé notify () ou notifyAll ().
La différence majeure est que wait () libère le verrou ou le moniteur en sleep () n'émet aucun verrou ni moniteur pendant l'attente. Wait est utilisé pour la communication inter-thread tandis que le sommeil est utilisé pour introduire une pause lors de l'exécution, en général.
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é, aucun autre thread ne peut entrer dans ce bloc ou cette méthode. Si un autre thread appelle t.interrupt (), il réactivera le thread en veille. Notez que le sommeil est une méthode statique, ce qui signifie qu’elle affecte toujours le thread actuel (celui qui exécute la méthode de veille). Une erreur courante consiste à appeler t.sleep () où t est un autre thread; même dans ce cas, c'est le thread actuel qui va dormir, pas le thread t.
object.wait () envoie le fil de discussion actuel à l'état "Non exécutable", comme sleep (), mais avec une torsion. Wait est appelé sur un objet, pas un thread; nous appelons cet objet "objet lock". Avant que lock.wait () soit appelé, le thread actuel doit se synchroniser sur l'objet lock; 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 verrou et appeler lock.notify (). Cela réveille le fil original en attente. Fondamentalement, wait ()/notify () est semblable à sleep ()/interrupt (), seul le thread actif n'a pas besoin d'un pointeur direct sur le thread en veille, mais uniquement sur l'objet verrou partagé.
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
Laisser classer tous les points ci-dessus:
Call on:
Synchronized:
Hold lock:
Wake-up condition:
Usage:
Réf: diff sleep
et wait
Les méthodes wait
et sleep
sont très différentes:
sleep
n'a aucun moyen de "se réveiller",wait
a une façon de se "réveiller" pendant la période d'attente, par un autre thread appelant notify
ou notifyAll
.À bien y penser, les noms sont déroutants à cet égard; Cependant, sleep
est un nom standard et wait
est semblable à WaitForSingleObject
ou WaitForMultipleObjects
dans l'API Win.
De cet article: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-Java/
1) Le thread qui appelle la méthode wait () libère le verrou qu’elle détient.
2) Le thread récupère 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 le verrouillage d'objet.
1) Le thread qui appelle la méthode sleep () ne libère pas le verrou qu’elle 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 en sommeil ne peuvent pas être réveillés par d'autres fils. Si cela est fait, le thread lèvera une exception InterruptedException.
5) Pour appeler la méthode sleep (), le thread n'a pas besoin de verrouiller l'objet.
En termes simples, wait est wait jusqu'à ce qu'un autre thread vous appelle alors que sleep est "n'exécutez pas la prochaine instruction" pendant une période donnée.
De plus, sleep est une méthode statique dans la classe Thread et fonctionne sur le thread, tandis que wait () est dans la classe Object et est appelé sur un objet.
Autre point, lorsque vous appelez wait sur un objet, le thread impliqué synchronise l’objet puis attend. :)
Une grande différence potentielle entre sommeil/interruption et attente/notification est que
interrupt()
pendant sleep()
lève toujours une exception (par exemple, InterruptedException ), alors quenotify()
pendant wait()
ne le fait pas.Générer une exception lorsqu'il n'est pas nécessaire est inefficace. Si vous avez des fils qui communiquent entre eux à un débit élevé, de nombreuses exceptions seraient générées si vous appeliez des interruptions tout le temps, ce qui représente un gaspillage total de ressources processeur.
wait()
est une méthode de Object
class.sleep()
est une méthode de Thread
class.
sleep()
permet au thread de passer à l'état sleep
pendant x millisecondes.
Quand un thread passe en état de veille it doesn’t release the lock
.
wait()
permet au thread de relâcher le verrou et goes to suspended state
.
Ce thread sera actif quand une méthode notify()
ou notifAll()
sera appelée pour le même objet.
Ici wait () sera dans l'état d'attente jusqu'à ce qu'il soit averti par un autre Thread, mais où sleep () aura un certain temps..après, il passera automatiquement à l'état Prêt ...
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 être averti. Il est possible de spécifier le temps d'attente maximal: Object.wait(5000)
afin qu'il soit possible d'utiliser wait
pour, euh, sleep
, mais vous devrez alors vous embêter avec les 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.
Recherchez vous-même: Le code source des méthodes natives est-il disponible? Le fichier /src/share/vm/prims/jvm.cpp
est le point de départ ...
Attendre () et dormir () Différences?
Thread.sleep () Une fois son travail terminé, il ne libère que le verrou à tout le monde. jusqu'à ce que son ne jamais libérer 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 en attente, il lâchera la clé et attendra quelques secondes en fonction du paramètre.
Par exemple:
vous prenez le café dans votre main droite, vous pouvez prendre une autre personne de la même main, quand vous posez alors seulement un autre objet du même type ici. aussi. c'est dormir () tu dors le temps tu ne travailles pas, tu ne fais que dormir .. pareil ici aussi.
attendez(). quand vous êtes couché 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 même en tant que lecteur, vous ne pouvez pas jouer plus d'un droit à la fois, c'est son ici, quand vous fermez et choisissez un autre film ou chanson signifie que vous attendez
wait
libère le verrou et sleep
ne le supprime pas. Un thread en attente est éligible pour se réveiller dès que notify
ou notifyAll
est appelé. Mais dans le cas de sleep
, le fil garde le verrou et il ne sera éligible qu'une fois le temps de sommeil écoulé.
Vous avez raison - Sleep () provoque la mise en veille de ce thread et le processeur s’éteint pour traiter d’autres threads (autrement connus sous le nom de commutation de contexte), ce qui, je le crois, permet au processeur de traiter le thread actuel.
Nous avons les deux parce que, même s'il peut sembler judicieux de laisser d'autres personnes utiliser le processeur alors que vous ne l'utilisez pas, le changement de contexte entraîne une surcharge. En fonction de la durée de veille, il peut être plus coûteux en cycles de processeur. pour changer de thread que ce soit simplement que votre thread ne fasse rien pendant quelques ms.
Notez également que le sommeil force le changement de contexte.
De plus, en général, il n'est pas possible de contrôler le changement de contexte. Pendant le délai d'attente, le système d'exploitation peut choisir (et attend plus longtemps) de traiter d'autres threads.
À mon avis, la principale différence entre les deux mécanismes est que veille/interruption est le moyen le plus fondamental de gérer les threads, alors que wait/notify est une abstraction destinée à faciliter l'intercommunication de threads. Cela signifie que dormir/interrompre peut faire n'importe quoi, mais cette tâche spécifique est plus difficile à faire.
Pourquoi attendre/notifier est-il plus approprié? Voici quelques considérations personnelles:
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.
La synchronisation est appliquée. Parce que le programmeur encapsule l'appel d'attendre/notifier dans un bloc synchronisé.
Il est indépendant du fil Origine et du nombre. Avec cette approche, vous pouvez ajouter plusieurs threads de façon arbitraire sans éditer les autres threads ni conserver une trace de ceux existants. Si vous avez utilisé veille/interruption, vous devez d’abord conserver les références aux threads en veille, puis les interrompre un à un, à la main.
Voici un exemple tiré de la vraie vie: 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 lieu central (un tableau en liège, une table, etc.), sonner une cloche, et les travailleurs de la cuisine viennent pour prendre de telles demandes. Une fois que tous les cours sont prêts, le personnel de la cuisine sonne à nouveau pour que les serveurs soient au courant et les apportent aux clients.
Depuis la page de documentation Oracle sur wait () méthode de Object
:
public final void wait()
notify()
ou la méthode notifyAll()
pour cet objet. En d'autres termes, cette méthode se comporte exactement comme si elle effectuait simplement l'appel wait(0)
.Cette méthode jette
IllegalMonitorStateException
- si le thread actuel n'est pas le propriétaire du moniteur de l'objet.
InterruptedException
- si un thread a interrompu le thread actuel avant ou pendant que le thread actuel attendait une notification. Le statut interrompu du thread en cours est effacé lorsque cette exception est levée.
De la page de documentation Oracle sur sleep () méthode de Thread
class:
public static void sleep(long millis)
Cette méthode jette:
IllegalArgumentException
- si la valeur en millis est négative
InterruptedException
- si un thread a interrompu le thread en cours. Le statut interrompu du thread en cours 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).
Exemple sur le sommeil ne libère pas le verrou et attend que le
Ici il y a deux classes:
Singleton: Il s'agit d'une 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, lancez 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 threadB attend à l'extérieur jusqu'à ce que threadA lâche le verrou.
Maintenant changez le Singleton.Java en commentant Thread.sleep (500); méthode et non commentée Singleton.class.wait (500); . Ici à cause de Singleton.class.wait (500); La méthode threadA libérera tous les verrous acquis et passera à l'état "non exécutable", threadB obtiendra la modification à entrer dans le bloc synchronisé.
Maintenant, lancez à 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 par threadB ne sont pas identiques, car threadB a dû changer pour entrer dans un bloc synchronisé et après 500 millisecondes, threadA a démarré à partir de sa dernière position et a créé un autre objet Singleton.
La méthode sleep()
a pour effet que le thread en cours passe de l'état d'exécution à l'état de blocage pendant un temps spécifié. Si le thread actuel a le verrou d'un objet, il le maintient, ce qui signifie que les autres threads ne peuvent exécuter aucune méthode synchronisée dans cet objet de classe.
La méthode wait()
a pour effet que le thread actuel passe à 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'appelant. objet.
Devrait être appelé à partir d'un bloc synchronisé: La méthode wait()
est toujours appelée à partir d'un bloc synchronisé, c'est-à-dire que la méthode wait()
doit verrouiller l'objet de contrôle avant objet sur lequel il s'appelle. Mais la méthode sleep()
peut être appelée de l'extérieur du bloc synchronisé, c'est-à-dire que la méthode sleep()
ne nécessite aucun moniteur d'objet.
IllegalMonitorStateException: si la méthode wait()
est appelée sans acquérir le verrou d'objet, alors que IllegalMonitorStateException
est lancé à l'exécution, mais sleep()
méthode ne jette jamais une telle exception.
Appartient à quelle classe: _ la méthode wait()
appartient à Java.lang.Object
classe mais la méthode sleep()
à Java.lang.Thread
classe.
Appelé sur un objet ou un fil: La méthode wait()
est appelée sur les objets mais la méthode sleep()
est appelée sur les threads et non les objets.
Etat du thread: lorsque la méthode wait()
est appelée sur un objet, le thread qui a gardé le moniteur de l'objet passe de l'état en attente à l'état actif et peut revenir à l'état en cours d'exécution. uniquement lorsque la méthode notify()
ou notifyAll()
est appelée sur cet objet. Et plus tard, le planificateur de threads planifie ce thread pour passer de l'état d'exécution à l'état d'exécution. Lorsque 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 repos est écoulé.
Lorsqu'il est appelé à partir d'un bloc synchronisé: lorsque la méthode wait()
est appelée, le thread quitte le verrouillage d'objet. Mais la méthode sleep()
lorsqu'elle est appelée à partir d'un bloc synchronisé ou d'un thread de méthode ne laisse pas le verrouillage d'objet.
Pour plus référence
En fait, tout cela est clairement décrit dans Java docs (mais je ne m'en suis rendu compte 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 jusqu'à ce qu'un autre thread informe les 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 reprend l'exécution.
sleep () - Met en veille le serveur en cours d'exécution (arrête temporairement l'exécution de l'exécution) pendant le nombre de millisecondes spécifié, sous réserve de la précision et de l'exactitude des temporisateurs et programmateurs du système. Le thread ne perd pas la propriété des moniteurs.
wait(1000)
provoque l’endormissement du thread actuel pendant une seconde au maximum . notify()
ou notifyAll()
.sleep(1000)
provoque l’endormissement du thread en cours pendant exactement 1 seconde . wait()
est donné dans une méthode synchronisée alors que sleep()
est donné dans une méthode non synchronisée car la méthode wait()
libère le verrou sur l'objet mais sleep()
ou yield()
libère-t-il la lock()
.
wait()
avec une valeur de délai d'attente peut se réveiller une fois la valeur de délai écoulée ou notifier celle qui est antérieure (ou l'interrompre également), alors qu'un sleep()
réveille la valeur de délai écoulé ou interrompre la première. wait()
sans valeur de délai d'attente attendra jusqu'à ce qu'il soit notifié ou interrompu.
Supposons que vous entendez des chansons.
Tant que la chanson en cours est en cours d'exécution, la chanson suivante ne sera pas lue, par exemple Sleep () appelée par la chanson suivante.
Si vous terminez la chanson, la lecture s'arrêtera et jusqu'à ce que vous sélectionniez le bouton de lecture (notify ()), la lecture sera interrompue, c'est-à-dire wait () appelé par la chanson en cours.
Dans ce cas, les chansons vont aux états d'attente.