Differenza tra wait () e sleep ()


1204

Qual'è la differenza tra a wait()e sleep()in Threads?

Comprendo che a wait()-ing Thread è ancora in modalità di esecuzione e utilizza cicli CPU ma a sleep()-ing non consuma alcun ciclo CPU corretto?

Perché abbiamo entrambi wait() e sleep(): in che modo la loro implementazione varia a un livello inferiore?


50
ottima domanda. la semantica di entrambi è facile da confondere.
Andreas Petersson,

1
Domande molto carine ma sono 2 in una. Perché abbiamo entrambi non è lo stesso di come possono (e non sono!) Implementati a un livello inferiore. Ho risposto anche a quello.
estani,

Supponiamo che un thread A sia in un blocco sincronizzato, e mentre è nella cpu da questo thread è preso e dato a un altro thread B. ora in quale stato passerà il thread A, gli altri thread in attesa su questo blocco sincronizzato entreranno ora ?
Peter,

1
Ecco un buon articolo che lo descrive: qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man

3
è ESCLUSIVAMENTE il contrario: sleep "utilizza" tutti i suoi cicli CPU disponibili ma poiché il thread sarà in "ATTESA", questi possono essere resi se necessario - in effetti la maggior parte dei sistemi operativi produce automaticamente i cicli SE è possibile, quindi il tuo thread non creerà alcun carico effettivo della CPU ... ma lo farà su sistemi operativi più vecchi. Object.wait (), d'altra parte non utilizza MAI alcun ciclo (pur non essendo notificato) perché realizzato in molti casi tramite interruzioni del software: blocchi privati, transitori e trasparenti, implementati da JVM. Thread.sleep è una cattiva pratica.
specializt

Risposte:


838

A waitpuò essere "svegliato" da un altro thread che chiama notifysul monitor che è in attesa mentre un sleepnon può. Anche un wait(e notify) deve accadere in un blocco synchronizedsull'oggetto monitor mentre sleepnon:

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

A questo punto il thread attualmente in esecuzione attende e rilascia il monitor . Un altro thread potrebbe fare

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

(sullo stesso monoggetto) e il primo thread (supponendo che sia l'unico thread in attesa sul monitor) si riattiverà.

Puoi anche chiamare notifyAllse più di un thread è in attesa sul monitor - questo li risveglierà tutti . Tuttavia, solo uno dei thread sarà in grado di afferrare il monitor (ricorda che waitè in asynchronized blocco) e andare avanti - gli altri verranno quindi bloccati fino a quando non potranno acquisire il blocco del monitor.

Un altro punto è che si chiama waitsu Objectse stesso (cioè l'attesa sul monitor di un oggetto), mentre si chiama sleepsu Thread.

Ancora un altro punto è che puoi ottenere spurie risvegli da wait(cioè il thread che sta aspettando riprende senza una ragione apparente). Dovresti sempre waitgirare su alcune condizioni come segue:

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

131
No non può. Può solo essere interrotto.
Peter Štibraný,

9
Quando si interrompe, è necessario sapere quale thread si desidera interrompere. Quando chiami notifica, hai solo bisogno di un oggetto e non ti importa se ci sono altri thread che 'aspettano' su questo oggetto. wait / notification è usato per la comunicazione, mentre sleep è usato per, ehm, sleep.
Peter Štibraný,

28
@Geek - perché nel mondo dici wait () spreca i cicli della CPU?
Robert Munteanu,

25
L'interruzione è intesa come un meccanismo per incoraggiare delicatamente un thread a interrompere completamente l'esecuzione e annullare le operazioni rimanenti. wait/ notifysono in genere utilizzati per attendere che un altro thread esegua un'attività o per attendere che una determinata condizione sia soddisfatta.
Louis Wasserman,

13
Ho letto tutte le risposte ma sento ancora un po 'di informazioni mancanti. Molte persone hanno scritto le definizioni del Javadoc e anche il significato delle due parole inglesi, ma non vedo Perché dovrei mai usare il sonno invece di aspettare? Qual è il benchmarking e la differenza di velocità tra i due? Se posso fare tutto ciò che posso fare con il sonno, perché dovrei mai scegliere di dormire?
Balazs Zsoldos,

334

Una differenza fondamentale non ancora menzionata è che durante la sospensione di un thread non rilascia i blocchi in suo possesso, mentre in attesa rilascia il blocco sull'oggetto che wait()viene chiamato.

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


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

105
In attesa rilascia solo il blocco per l'oggetto che si chiama wait (). Non rilascia altri blocchi.
Jon Skeet,

16
In realtà non è necessario chiamare il sonno dall'interno di un blocco: i blocchi e l'attesa / notifica vanno di pari passo, ma i blocchi e il sonno non sono correlati.
oxbow_lakes,

7
@oxbow_lakes - Direi che non dovresti dormire con i lucchetti, ci sono pochi casi d'uso per questo. Volevo solo sottolineare le differenze.
Robert Munteanu,

5
@RobertMunteanu, La tua risposta afferma in modo fuorviante che sleepdetiene i blocchi Java , ma non lo è. Per avere un confronto equo, faremmo un confronto synchronized(OUTER_LOCK){ Thread.sleep(1000); }con synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }e possiamo vedere che entrambe le istruzioni non rilasciano il OUTER_LOCK. Se c'è qualche differenza, possiamo dire che sleepnon usa esplicitamente i blocchi java , ma la domanda è sul preventivo "come varia la loro implementazione a un livello inferiore?" unquote.
Pacerier,

2
@Pacerier wait()è associato alla condizione del blocco più interno da cui viene chiamato, nel tuo esempio di codice, wait()può solo rilasciare LOCKe non OUTER_LOCK. Ecco come è progettato comunque il monitor Java. Un confronto equo sarebbe synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }e synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. In questo caso sleep()conterrà entrambi i blocchi mentre wait()si rilascia LOCKma continuerà a tenere premutoOUTER_LOCK
danze

244

Ho trovato questo post utile . Si mette la differenza tra Thread.sleep(), Thread.yield()e Object.wait()in termini umani. Per citare:

Alla fine si fa strada fino allo scheduler del sistema operativo, che distribuisce i tempi a processi e thread.

sleep(n) dice "Ho finito con il mio timeslice, e per favore non darmene un altro per almeno n millisecondi." Il sistema operativo non prova nemmeno a pianificare il thread in sospeso fino a quando non è trascorso il tempo richiesto.

yield() dice "Ho finito con il mio timeslice, ma ho ancora del lavoro da fare." Il sistema operativo è libero di assegnare immediatamente un altro thread al thread, oppure di assegnare qualche altro thread o elaborare alla CPU il thread cedente appena rinunciato.

wait()dice "Ho finito con il mio timeslice. Non darmi un'altra scorciatoia fino a quando qualcuno chiama notification (). "Analogamente sleep(), il sistema operativo non tenterà nemmeno di pianificare l'attività a meno che qualcuno non chiami notify()(o si verifichi uno degli altri scenari di riattivazione).

I thread perdono anche il resto della sequenza temporale quando eseguono l'IO bloccante e in alcune altre circostanze. Se un thread funziona attraverso l'intera finestra temporale, il sistema operativo assume il controllo forzatamente all'incirca come seyield() fosse stato chiamato, in modo che altri processi possano essere eseguiti.

Raramente è necessario yield(), ma se si dispone di un'app pesante di calcolo con limiti logici di attività, l'inserimento di una yield() potrebbe migliorare la reattività del sistema (a scapito del tempo - i cambi di contesto, anche solo per il sistema operativo e viceversa, non sono gratuiti). Misura e metti alla prova gli obiettivi che ti interessano, come sempre.


La resa dipende sostanzialmente dalla piattaforma ... javamex.com/tutorials/threads/yield.shtml
Pacerier

la spiegazione di sleep(n)sta implicitamente dicendo che il thread attualmente in esecuzione rinuncia volontariamente al monitor del lock, il che non è vero . Citazione dal javadoc di Thread : "Il thread non perde la proprietà di alcun monitor".
Clint Eastwood,

2
@Jonathan non c'è menzione dei monitor nella risposta, e questo perché sleepnon ha alcun comportamento speciale riguardo ai monitor rispetto a qualsiasi altra chiamata al metodo Java, cioè non li interagisce o li modifica in alcun modo. Se dovessi dire qualcosa sui monitor, dovresti specificare che wait, oltre a quanto detto sopra, rinuncerà temporaneamente al blocco sull'oggetto su cui viene chiamato.
pqnet,

Come funziona la notifica a livello di scheduler del sistema operativo? Notifica chiama una sorta di gestore di eventi con un particolare ID thread, consentendo allo scheduler di riportare il thread rilevante sulla coda in esecuzione? Inoltre ho un'altra domanda: dove si inserisce il concetto di spinlock? Sarebbe rilevante solo per il sonno o aspetta se stesso usare spinlock a un livello molto basso?
CMCDragonkai,

@Erich, usare wait(n)per confrontare sleep(n). Non ha senso confrontarsi con il no-arg.
Pacerier

68

Ci sono molte risposte qui ma non sono riuscito a trovare la distinzione semantica menzionata su nessuna.

Non si tratta del thread stesso; entrambi i metodi sono richiesti in quanto supportano casi d'uso molto diversi.

sleep()invia il thread alla modalità di sospensione come prima, impacchetta semplicemente il contesto e interrompe l'esecuzione per un tempo predefinito. Quindi, per svegliarlo prima del dovuto, è necessario conoscere il riferimento al thread. Questa non è una situazione comune in un ambiente multi-thread. Viene utilizzato principalmente per la sincronizzazione temporale (ad es. Sveglia in esattamente 3,5 secondi) e / o equità codificata (basta dormire un po 'e lasciare che gli altri thread funzionino).

wait()al contrario, è un meccanismo di sincronizzazione di thread (o messaggi) che consente di notificare un thread di cui non si ha alcun riferimento memorizzato (né cura). Puoi considerarlo come un modello di pubblicazione-iscrizione ( wait== iscriviti enotify() == pubblica). Fondamentalmente usando Notify () stai inviando un messaggio (che potrebbe anche non essere ricevuto affatto e normalmente non ti interessa).

Per riassumere, normalmente si usa sleep()per la sincronizzazione temporale e wait()per la sincronizzazione multi-thread.

Potrebbero essere implementati allo stesso modo nel sistema operativo sottostante o per niente (dato che le versioni precedenti di Java non avevano un vero multithreading; probabilmente anche alcune piccole macchine virtuali non lo fanno). Non dimenticare che Java gira su una VM, quindi il tuo codice verrà trasformato in qualcosa di diverso a seconda della VM / OS / HW su cui gira.


54

Qui, ho elencato alcune differenze importanti tra wait()e sleep()metodi.
PS: clicca anche sui link per vedere il codice della libreria (funzionamento interno, basta giocare un po 'per capire meglio).

aspettare()

  1. wait() Il metodo rilascia il blocco.
  2. wait() è il metodo di Object classe.
  3. wait() è il metodo non statico - public final void wait() throws InterruptedException { //...}
  4. wait()dovrebbe essere notificato con notify()o notifyAll()metodi.
  5. wait() Il metodo deve essere chiamato da un loop per gestire i falsi allarmi.

  6. wait() Il metodo deve essere chiamato dal contesto sincronizzato (ovvero metodo o blocco sincronizzato), altrimenti verrà generato IllegalMonitorStateException

dormire()

  1. sleep() il metodo non rilascia il blocco.
  2. sleep() è il metodo di java.lang.Thread classe.
  3. sleep() è il metodo statico - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. dopo il periodo di tempo specificato, sleep() è completato.
  5. sleep()meglio non chiamare dal loop (es. vedi codice sotto ).
  6. sleep()può essere chiamato da qualsiasi luogo. non esiste un requisito specifico.

Rif: differenza tra attendere e dormire

Frammento di codice per la chiamata del metodo wait e sleep

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

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

passaggio del thread a diversi stati del thread


È corretto che un thread inattivo possa essere svegliato dalle chiamate per avvisare ()? Alcuni degli altri post qui sembrano implicare che un thread dormiente non può essere svegliato ma interrotto.
Berimbolo,

Sì, Thread.sleep()è utilizzato per rendere il tempo del processore disponibile per gli altri thread. il periodo di sospensione può essere interrotto da interruzioni (ovvero da JVM). Leggi questo stackoverflow.com/questions/4264355/...
roottraveller

Quel post dice anche che interrupt () è ciò che sveglia un thread dormiente? Mi riferivo al diagramma di stato del thread che hai pubblicato in cui si dice notifica o notifica Tutti riportano un thread inattivo (non in attesa) per essere pronto per l'esecuzione. Voglio solo assicurarmi di capirlo.
Berimbolo,

@berimbolo notify()o notifyAll()sono Objectmetodi di classe. quindi sono disponibili per tutta la classe (cioè anche qui con la Threadclasse). vedere il codice grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

2
OK Ho bisogno di leggere di più sulla pianificazione dei thread in quanto non riesco a trovare esempi di wake () o wakeAll () che riattiva i thread in sospensione solo interrompendo () facendo questo. Tutti gli esempi si riferiscono a notify () e notifyAll () ai thread in attesa su alcuni oggetti monitor.
Berimbolo,

29

Ci sono alcune note chiave sulla differenza che concludo dopo aver lavorato su wait e sleep, per prima cosa dai un'occhiata all'esempio usando wait () e sleep ():

Esempio 1 : utilizzo di wait () e 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();
}

Chiarisci alcune note chiave:

  1. Chiama :
    • wait (): chiama il thread corrente che contiene HandObject Object
    • sleep (): Call on Thread esegue task get beer (è il metodo class quindi influenza sul thread in esecuzione corrente)
  2. Sincronizzato :
    • wait (): quando l'accesso multi-thread sincronizzato accede allo stesso oggetto (HandObject) (quando è necessaria la comunicazione tra più thread (thread esegui codifica, thread esegui ottieni birra) accedi allo stesso oggetto HandObject)
    • sleep (): durante l'attesa per continuare l'esecuzione (Waiting beer disponibile)
  3. Blocco blocco :
    • wait (): rilascia il blocco per altri oggetti che hanno la possibilità di eseguire (HandObject è gratuito, puoi fare altro lavoro)
    • sleep (): mantenere il blocco per almeno t volte (o fino all'interruzione) (Il mio lavoro non è ancora terminato, continuo a bloccare il blocco e in attesa che alcune condizioni continuino)
  4. Condizioni di sveglia :
    • wait (): fino alla chiamata notification (), notifyAll () dall'oggetto
    • sleep (): fino almeno alla scadenza del tempo o alla chiamata di interruzione
  5. E l'ultimo punto è usare quando gli estani indicano:

normalmente usi sleep () per la sincronizzazione temporale e wait () per la sincronizzazione multi-thread.

Per favore correggimi se sbaglio.


26

Differenza tra wait () e sleep ()

  • La differenza fondamentale è che wait()proviene da Objected sleep()è un metodo statico di Thread.

  • La differenza principale è che wait()rilascia il blocco mentre sleep()non rilascia alcun blocco durante l'attesa.

  • wait()è usato per la comunicazione tra thread mentre sleep()è usato per introdurre una pausa nell'esecuzione, generalmente.

  • wait()dovrebbe essere chiamato dall'interno di sincronizzazione o altrimenti otteniamo un IllegalMonitorStateException, mentre sleep() può essere chiamato ovunque.

  • Per ricominciare una discussione wait(), devi chiamare notify()o notifyAll(). Per quanto riguarda sleep(),il thread inizia dopo un intervallo di tempo specificato.

Somiglianze

  • Entrambi fanno passare il thread corrente allo stato Non eseguibile .
  • Entrambi sono metodi nativi .

18

Questa è una domanda molto semplice, perché entrambi questi metodi hanno un uso totalmente diverso.

La differenza principale è attendere il rilascio del blocco o del monitor mentre il sonno non rilascia alcun blocco o monitor durante l'attesa. L'attesa viene utilizzata per la comunicazione tra thread mentre sleep viene utilizzato per introdurre la pausa durante l'esecuzione.

Questa era solo una spiegazione chiara e di base, se vuoi di più, continua a leggere.

Nel caso in cui il wait()thread del metodo vada in stato di attesa e non ritorni automaticamente fino a quando non chiamiamo il notify()metodo (o notifyAll()se hai più di un thread in stato di attesa e vuoi riattivare tutto quel thread). E hai bisogno di sincronizzare o il blocco degli oggetti o il blocco della classe per accedere ai metodi wait()o notify()o notifyAll(). E un'altra cosa, ilwait() metodo viene utilizzato per la comunicazione tra thread perché se un thread passa in stato di attesa, è necessario un altro thread per riattivare quel thread.

Ma in questo caso sleep()è un metodo che viene utilizzato per mantenere il processo per alcuni secondi o il tempo desiderato. Perché non è necessario provocare alcun metodo notify()o notifyAll()per riavere quel thread. Oppure non hai bisogno di nessun altro thread per richiamare quel thread. Ad esempio, se vuoi che qualcosa accada dopo pochi secondi, come in una partita dopo il turno dell'utente, vuoi che l'utente attenda fino alla riproduzione del computer, quindi puoi menzionare il sleep()metodo.

E un'altra importante differenza che viene chiesta spesso nelle interviste: sleep()appartiene alla Threadclasse e wait()appartiene alla Objectclasse.

Queste sono tutte le differenze tra sleep()e wait().

E c'è una somiglianza tra i due metodi: entrambi sono istruzioni verificate, quindi è necessario provare a catturare o lanciare per accedere a questi metodi.

Spero che questo ti possa aiutare.


16

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

Thread.sleep()invia il thread corrente allo stato "Non eseguibile" per un certo periodo di tempo. Il thread mantiene i monitor acquisiti, ovvero se il thread è attualmente in un blocco o metodo sincronizzato, nessun altro thread può accedere a questo blocco o metodo. Se viene chiamato un altro thread, il thread inattivo t.interrupt()verrà attivato.

Si noti che sleep è un metodo statico, il che significa che influenza sempre il thread corrente (quello che sta eseguendo il metodo sleep). Un errore comune è chiamare t.sleep()dove t è un thread diverso; anche allora, sarà il thread corrente a dormire, non il thread t.

t.suspend()è deprecato. Usandolo è possibile arrestare un thread diverso dal thread corrente. Un thread sospeso mantiene tutti i suoi monitor e poiché questo stato non è interrompibile, è soggetto a deadlock.

object.wait()invia il thread corrente nello stato "Non eseguibile" , come sleep(), ma con una svolta. L'attesa viene chiamata su un oggetto, non su un thread; chiamiamo questo oggetto "oggetto di blocco". Prima che lock.wait()venga chiamato, il thread corrente deve sincronizzarsi sull'oggetto lock; wait() quindi rilascia questo blocco e aggiunge il thread alla "lista di attesa" associata al blocco. Successivamente, un altro thread può sincronizzarsi sullo stesso oggetto di blocco e chiamare lock.notify(). Questo riattiva il thread di attesa originale. Fondamentalmente, wait()/ notify()è come sleep()/ interrupt(), solo il thread attivo non ha bisogno di un puntatore diretto al thread dormiente, ma solo all'oggetto lock condiviso.


14

Aspettare e dormire sono due cose diverse:

  • Nel sleep()thread smette di funzionare per la durata specificata.
  • Nel wait()thread smette di funzionare fino a quando l'oggetto in attesa non viene notificato, generalmente da altri thread.

ma puoi interrompere un thread dormiente. In tal caso wait () è ridondante infatti spreca anche i cicli della CPU :-(
Geek

9
L'attesa non spreca i cicli della CPU.
Peter Štibraný,

1
@Peter - Penso di si. Attende () il suo blocco di cicli della CPU e quindi il sistema operativo fornisce i cicli della CPU ad altri thread. Penso che questo potrebbe dipendere dal sistema operativo, non ne sono sicuro.
Geek,

3
Sarebbe una implementazione molto scarsa di wait () se sprecasse cicli della CPU. wait / notification è usato parecchio per la comunicazione interthread.
Peter Štibraný,

2
@Pacerier i due costrutti sono destinati a uno scopo diverso. Se vuoi che un thread si fermi per un periodo di tempo fisso che usi sleep, se vuoi che si fermi fino a quando alcuni input provengono dall'altro che usi wait/ notify. interruptè inteso come un modo per segnalare a un thread che dovrebbe smettere di fare ciò che sta facendo e terminare. È gestito da sleep, waitma anche bloccando le funzioni I / O (e potresti implementare funzioni con lo stesso comportamento chiamando il metodo Thread.interrupted()). Per quanto riguarda le prestazioni, le funzioni sono generalmente ottimizzate per l'obiettivo che sono state progettate.
pqnet,

11

sleepè un metodo di Thread, waitè un metodo di Object, quindi wait/notifyè una tecnica di sincronizzazione dei dati condivisi in Java (usando monitor ), ma sleepè un semplice metodo di thread per mettere in pausa se stesso.


8

sleep () è un metodo che viene utilizzato per trattenere il processo per alcuni secondi o il tempo desiderato, ma in caso di attesa () il thread del metodo passa in stato di attesa e non ritorna automaticamente fino a quando non chiamiamo notification () o notifyAll ().

La differenza principale è che wait () rilascia il blocco o il monitor mentre sleep () non rilascia alcun blocco o monitor durante l'attesa. L'attesa viene utilizzata per la comunicazione tra thread mentre sleep viene utilizzato per introdurre una pausa durante l'esecuzione, in generale.

Thread.sleep () invia il thread corrente allo stato "Non eseguibile" per un certo periodo di tempo. Il thread mantiene i monitor che ha acquisito, ovvero se il thread è attualmente in un blocco o metodo sincronizzato, nessun altro thread può inserire questo blocco o metodo. Se un altro thread chiama t.interrupt (), il thread inattivo verrà attivato. Si noti che sleep è un metodo statico, il che significa che influenza sempre il thread corrente (quello che sta eseguendo il metodo sleep). Un errore comune è chiamare t.sleep () dove t è un thread diverso; anche allora, sarà il thread corrente a dormire, non il thread t.

object.wait () invia il thread corrente nello stato "Non eseguibile", come sleep (), ma con una svolta. L'attesa viene chiamata su un oggetto, non su un thread; chiamiamo questo oggetto "oggetto di blocco". Prima di chiamare lock.wait (), il thread corrente deve sincronizzarsi sull'oggetto lock; wait () quindi rilascia questo blocco e aggiunge il thread alla "lista di attesa" associata al blocco. Successivamente, un altro thread può sincronizzarsi sullo stesso oggetto lock e chiamare lock.notify (). Questo riattiva il thread di attesa originale. In sostanza, wait () / notification () è come sleep () / interrupt (), solo il thread attivo non ha bisogno di un puntatore diretto al thread inattivo, ma solo all'oggetto lock condiviso.

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

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

Lascia che categorizzi tutti i punti sopra:

Call on:

  • wait (): chiama un oggetto; il thread corrente deve sincronizzarsi sull'oggetto lock.
  • sleep (): chiama un thread; eseguendo sempre thread attualmente.

Synchronized:

  • wait (): quando più thread sincronizzati accedono allo stesso oggetto uno per uno.
  • sleep (): quando più thread sincronizzati attendono lo sleep del thread inattivo.

Hold lock:

  • wait (): rilascia il blocco per consentire ad altri oggetti di essere eseguiti.
  • sleep (): mantenere il blocco per almeno t volte se viene specificato il timeout o se qualcuno lo interrompe.

Wake-up condition:

  • wait (): fino alla chiamata notification (), notifyAll () dall'oggetto
  • sleep (): fino almeno alla scadenza del tempo o alla chiamata di interrupt ().

Usage:

  • sleep (): per la sincronizzazione oraria e;
  • wait (): per la sincronizzazione multi-thread.

Rif: diff sleepewait


6

In parole semplici, wait is wait Fino a quando un altro thread non ti invoca, mentre sleep è "non eseguire la prossima istruzione" per un determinato periodo di tempo.

Inoltre, sleep è un metodo statico nella classe Thread e funziona su thread, mentre wait () è in classe Object e chiamato su un oggetto.

Un altro punto, quando si chiama wait su un oggetto, il thread coinvolto sincronizza l'oggetto e quindi attende. :)


1
Perché hai bisogno di entrambi? Perché sleep () non è sufficiente?
Geek,

2
Notifica viene utilizzato per la comunicazione tra i thread. Per chiamare wait, hai bisogno di qualche oggetto, sincronizzalo e quindi chiama wait su di esso. Per ricevere una notifica, è necessario che altri thread si sincronizzino sullo stesso oggetto e chiamino notifica.
Peter Štibraný,

6

wait e sleep metodi sono molto diversi:

  • sleep non ha modo di "svegliarsi",
  • mentre waitha un modo di "svegliarsi" durante il periodo di attesa, con un altro thread che chiama notifyonotifyAll .

Vieni a pensarci, i nomi sono confusi in questo senso; tuttavia sleepè un nome standard ed waitè simile all'API Win WaitForSingleObjecto WaitForMultipleObjects.


3
Ma possiamo interrompere un sonno, no? quindi qual è la differenza con quel sonno / interruzione vs attesa / notifica?
Pacerier

2
Puoi interrompere una persona che dorme, ma puoi avvisare solo una persona in attesa. Le discussioni sono uguali.
Rishi,

5

Da questo post: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

wait () Metodo.

1) Il thread che chiama il metodo wait () rilascia il blocco in suo possesso.

2) Il thread riacquista il blocco dopo che altri thread chiamano i metodi notify () o notifyAll () sullo stesso blocco.

3) Il metodo wait () deve essere chiamato all'interno del blocco sincronizzato.

4) Il metodo wait () viene sempre chiamato sugli oggetti.

5) I thread in attesa possono essere attivati ​​da altri thread chiamando i metodi notify () o notifyAll ().

6) Per chiamare il metodo wait (), il thread deve avere il blocco degli oggetti.

Metodo sleep ()

1) Il thread che chiama il metodo sleep () non rilascia il blocco che contiene.

2) Il metodo sleep () può essere chiamato all'interno o all'esterno del blocco sincronizzato.

3) Il metodo sleep () viene sempre chiamato sui thread.

4) I thread dormienti non possono essere svegliati da altri thread. Altrimenti, il thread genererà InterruptedException.

5) Per chiamare il metodo sleep (), il thread non deve avere il blocco degli oggetti.


4

Qui wait () sarà nello stato di attesa fino a quando non verrà notificato da un altro thread, ma dove sleep () avrà un po 'di tempo ... dopo che passerà automaticamente allo stato Pronto ...


4
  1. wait()è un metodo di Objectclasse.
    sleep()è un metodo di Threadclasse.

  2. sleep()consente al thread di andare allo sleepstato per x millisecondi.
    Quando un thread entra in stato di sospensione it doesn’t release the lock.

  3. wait()consente al thread di rilasciare il blocco e goes to suspended state.
    Questo thread sarà attivo quando viene chiamato un metodo notify()o notifAll()per lo stesso oggetto.


4

Una potenziale grande differenza tra sospensione / interruzione e attesa / notifica è quella

Generare un'eccezione quando non necessario è inefficiente. Se hai thread che comunicano tra loro ad alta velocità, genererebbe molte eccezioni se chiamassi interrupt tutto il tempo, il che è uno spreco totale di CPU.


+1, un valido punto di fatto, anche se a discutere sui meccanismi interni di implementazioni possono essere più rilevanti per l'analisi delle prestazioni ...
Pacerier

In altre parole, l'overhead della creazione di eccezioni potrebbe essere significativamente inferiore rispetto al overhead dell'implementazione del sistema dell'uno rispetto all'altro.
Pacerier

3

Hai ragione - Sleep () fa sì che il thread si "sleep" e la CPU si spenga ed elabori altri thread (altrimenti noti come commutazione di contesto) dove credo che Wait continui a processare la CPU.

Abbiamo entrambi perché, anche se può sembrare ragionevole lasciare che altre persone utilizzino la CPU mentre non la si utilizza, in realtà c'è un sovraccarico al cambio di contesto - a seconda di quanto dura il sonno, può essere più costoso nei cicli della CPU per cambiare thread di quanto non sia semplicemente fare in modo che il thread non faccia nulla per alcuni ms.

Si noti inoltre che il sonno forza un cambio di contesto.

Inoltre - in generale non è possibile controllare il cambio di contesto - durante l'attesa il sistema operativo può (e farà attendere più a lungo) la scelta di elaborare altri thread.


4
wait () non consente alla CPU di elaborare il thread corrente. È come dormire perché causa anche un cambio di contesto: javamex.com/tutorials/threads/context_switch.shtml . Sto chiedendo da sei mesi tutto lo stackoverflow e sembra che nessuno sappia qual è la differenza tra wait / notification vs sleep / interrupt.
Pacerier,

sebbene la sospensione non mantenga la CPU nell'elaborazione del thread corrente, penso che sia comunque un po 'un peso per la CPU, perché la CPU deve tenere traccia del momento in cui terminare la sospensione. Non ha quel trigger esterno come "notifica" in attesa. No?
Vladimir Nabokov,

@VladimirNabokov, Il trigger esterno è interrupt. L'ora di fine è ntra wait(n). ¶¶ Sono passati 8 anni e nessuno ha ancora la risposta!
Pacerier

3

I metodi sono usati per cose diverse.

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

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

Thread.sleep (n) può essere interrotto, ma Object.wait () deve essere avvisato. È possibile specificare il tempo massimo di attesa: Object.wait(5000)quindi sarebbe possibile usarlo wait, sleepma poi devi preoccuparti dei blocchi.

Nessuno dei due metodi utilizza la CPU durante il sonno / attesa.

I metodi sono implementati usando codice nativo, usando costrutti simili ma non allo stesso modo.

Cerca te stesso: è disponibile il codice sorgente dei metodi nativi? Il file /src/share/vm/prims/jvm.cppè il punto di partenza ...


Il timing thread.sleep può anche essere impostato su indefinito. Il timing di Object.wait può anche essere impostato su definito. Questa risposta non spiega perché abbiamo bisogno di 2 martelli che fanno la stessa cosa.
Pacerier,

Thread.sleep(big_num) deve essere interrotto. Object.wait(small_num) può essere avvisato.
Pacerier

3

Aspettare () e dormire () Differenze?

Thread.sleep () Una volta completato il suo lavoro, rilascia solo il blocco a tutti. fino a quando non rilasciare mai il blocco a nessuno.

  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 () Quando sta per attendere in fase, rilascerà la chiave e attenderà alcuni secondi in base al parametro.

Per esempio:

prendi il caffè nella tua mano destra, puoi prenderne un altro della stessa mano, quando lo poserai, prendi solo un altro oggetto dello stesso tipo qui. anche. questo è sonno () tu dormi non hai lavorato, fai solo dormire .. lo stesso anche qui.

aspettare(). quando sei messo giù e prendi un altro mezzo mentre aspetti, è aspettare

stai riproducendo un film o qualsiasi altra cosa nel tuo sistema come un giocatore che non puoi riprodurre più di uno alla volta, ecco qui, quando chiudi e scegli un altro film o canzone che significa mentre è chiamato wait


3

waitrilascia il blocco e sleepnon lo fa. Un thread in stato di attesa è idoneo al risveglio non appenanotify o notifyAllviene chiamato. Ma nel caso in cui sleepil thread mantenga il blocco e sarà idoneo solo al termine del tempo di sospensione.


Quindi se il thread è inattivo per 10 secondi e si verifica un'eccezione interrotta ????
Geek,

@Geek An InterruptedExceptionviene lanciato, proprio come dice nel Javadoc.
Marchese di Lorne,

@EJP: sei lo stesso EJP che era nei forum sun.java.com? Almeno il tuo punteggio suggerisce lo stesso :-)
Geek

2

sleep()Il metodo fa sì che il thread corrente passi dallo stato in esecuzione allo stato di blocco per un tempo specificato. Se il thread corrente ha il blocco di qualsiasi oggetto, continua a trattenerlo, il che significa che altri thread non possono eseguire alcun metodo sincronizzato nell'oggetto classe.

wait() Il metodo fa sì che il thread corrente vada nello stato di blocco per un tempo specificato o fino alla notifica, ma in questo caso il thread rilascia il blocco dell'oggetto (il che significa che altri thread possono eseguire qualsiasi metodo sincronizzato dell'oggetto chiamante.


2

A mio avviso, la differenza principale tra entrambi i meccanismi è che sleep / interrupt è il modo più semplice di gestire i thread, mentre wait / notification è un'astrazione volta a facilitare l'intercettazione dei thread. Ciò significa che sleep / interrupt può fare qualsiasi cosa, ma che questo compito specifico è più difficile da svolgere.

Perché aspettare / avvisare è più adatto? Ecco alcune considerazioni personali:

  1. Fa applicare la centralizzazione. Permette di coordinare la comunicazione tra un gruppo di thread con un singolo oggetto condiviso. Questo semplifica molto il lavoro.

  2. Applica la sincronizzazione. Perché fa sì che il programmatore avvolga la chiamata in attesa / notifica in un blocco sincronizzato.

  3. È indipendente dall'origine e dal numero del thread. Con questo approccio è possibile aggiungere più thread arbitrariamente senza modificare gli altri thread o tenere traccia di quelli esistenti. Se hai usato sleep / interrupt, prima dovresti conservare i riferimenti ai thread dormienti, quindi interromperli uno a uno, a mano.

Un esempio della vita reale che è buono per spiegare questo è un ristorante classico e il metodo che il personale usa per comunicare tra loro: i camerieri lasciano le richieste dei clienti in un posto centrale (una bacheca di sughero, un tavolo, ecc.), suona un campanello e gli operai della cucina vengono a prendere tali richieste. Una volta che c'è un corso pronto, il personale della cucina suona di nuovo il campanello in modo che i camerieri siano consapevoli e li portino ai clienti.


2

Un esempio di sospensione non rilascia il blocco e aspetta

Qui ci sono due classi:

  1. Principale : contiene il metodo principale e due thread.
  2. Singleton : questa è la classe singleton con due metodi statici getInstance () e getInstance (booleano 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();
    
     }
    }

e

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;

 }
}

Ora esegui questo esempio otterrai l'output seguente:

_instance :null
Both singleton are same

Qui le istanze Singleton create da threadA e threadB sono uguali. Significa che il thread B è in attesa all'esterno fino a quando il thread A non è bloccato.

Ora cambia Singleton.java commentando Thread.sleep (500); metodo e decommentando Singleton.class.wait (500); . Qui a causa di Singleton.class.wait (500); il metodo threadA rilascerà tutti i blocchi acquisiti e si sposta nello stato "Non eseguibile", il thread B riceverà le modifiche per entrare nel blocco sincronizzato.

Ora corri di nuovo:

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

Qui le istanze Singleton create da threadA e threadB NON sono uguali a causa di threadB che ha ricevuto modifiche per entrare nel blocco sincronizzato e dopo 500 millisecondi threadA è partito dalla sua ultima posizione e ha creato un altro oggetto Singleton.


2

Dovrebbe essere chiamato dal blocco sincronizzato: il wait() metodo viene sempre chiamato dal blocco sincronizzato, ovvero il wait()metodo deve bloccare il monitoraggio degli oggetti prima dell'oggetto su cui viene chiamato. Ma il sleep()metodo può essere chiamato da un blocco sincronizzato esterno, cioè il sleep()metodo non ha bisogno di alcun monitor di oggetti.

IllegalMonitorStateException: se il wait()metodo viene chiamato senza acquisire il blocco degli oggetti rispetto a quello IllegalMonitorStateExceptionlanciato in fase di esecuzione, ma il sleep()metodo non genera mai tale eccezione.

Appartiene a quale classe: il wait() metodo appartiene alla java.lang.Objectclasse ma il sleep()metodo appartiene alla java.lang.Threadclasse.

Chiamato su oggetto o thread: il wait() metodo viene chiamato su oggetti ma il sleep()metodo viene chiamato su Thread non su oggetti.

Stato del thread: quando wait()viene chiamato il metodo sull'oggetto, il thread che ha tenuto il monitor dell'oggetto passa dallo stato di esecuzione a quello di attesa e può tornare allo stato eseguibile solo quando notify()o il notifyAll()metodo viene chiamato su quell'oggetto. E in seguito lo scheduler del thread pianifica che il thread passi dallo stato eseguibile a quello in esecuzione. quandosleep() viene chiamato sul thread, passa dallo stato di esecuzione allo stato di attesa e può tornare allo stato di esecuzione quando il tempo di sospensione è scaduto.

Quando viene chiamato dal blocco sincronizzato: quando il wait()metodo viene chiamato thread lascia il blocco dell'oggetto. Masleep() metodo quando viene chiamato dal blocco sincronizzato o dal thread del metodo non lascia il blocco degli oggetti.

Per ulteriori riferimenti


probabilmente un URL di riferimento migliore di quello.
Ha

2

Dalla pagina della documentazione di Oracle sul metodo wait () di Object:

public final void wait()
  1. Fa in modo che il thread corrente attenda fino a quando un altro thread invoca il notify()metodo o il notifyAll()metodo per questo oggetto. In altre parole, questo metodo si comporta esattamente come se eseguisse semplicemente la chiamatawait(0) .
  2. Il thread corrente deve possedere il monitor di questo oggetto. Il thread rilascia la proprietà di questo monitor e attende fino a quando un altro thread non notifica ai thread in attesa sul monitor di questo oggetto di riattivarsi
  3. sono possibili interruzioni e risvegli spuri
  4. Questo metodo deve essere chiamato solo da un thread proprietario del monitor di questo oggetto

Questo metodo genera

  1. IllegalMonitorStateException - se il thread corrente non è il proprietario del monitor dell'oggetto.

  2. InterruptedException- se qualche thread ha interrotto il thread corrente prima o mentre il thread corrente era in attesa di una notifica. Lo stato interrotto del thread corrente viene cancellato quando viene generata questa eccezione.

Dalla pagina della documentazione di Oracle sul metodo di classe sleep ()Thread :

public static void sleep(long millis)
  1. Fa in modo che il thread attualmente in esecuzione venga sospeso (interrompa temporaneamente l'esecuzione) per il numero specificato di millisecondi, soggetto alla precisione e all'accuratezza dei timer e degli scheduler del sistema.
  2. Il thread non perde la proprietà di alcun monitor.

Questo metodo genera:

  1. IllegalArgumentException - se il valore di millis è negativo

  2. InterruptedException- se qualche thread ha interrotto il thread corrente. Lo stato interrotto del thread corrente viene cancellato quando viene generata questa eccezione.

Altra differenza chiave:

wait()è un metodo non statico (metodo di istanza) a differenza del metodo statico sleep()(metodo di classe).


1

wait()è dato all'interno di un metodo sincronizzato che sleep()viene proposta all'interno di un metodo non sincronizzato perché wait()metodo rilascia il blocco sull'oggetto ma sleep()o yield()fa rilasciare il lock().


sleep()può essere all'interno di un synchronizedblocco o metodo. La risposta non spiega nulla.
Marchese di Lorne,

1
  • Il metodo wait(1000)fa dormire il thread corrente fino a un secondo .
    • Un thread potrebbe dormire meno di 1 secondo se riceve la chiamata del metodo notify()onotifyAll() .
  • La chiamata a sleep(1000)causa la sospensione del thread corrente per esattamente 1 secondo .
    • Anche il thread dormiente non trattiene il blocco di alcuna risorsa . Ma aspettare thread lo fa.

1
sleep(1000)non garantisce di dormire esattamente per 1 secondo. Potrebbe essere stato interrotto prima.
Lucio,

1
Questi post sono così confusi. Tutti gli altri post su questa discussione dicono che un thread in sospeso NON tiene il blocco e che un thread in attesa NON tiene il blocco. Allo stesso modo, il post con il diagramma implica che le chiamate per avvisare () riattivare i thread in sospensione, ma altri post (e diagrammi di stato del thread) implicano che solo l'interrupt () o il periodo di timeout che passa fanno questo. Mi sono appena ordinato una copia della concorrenza java in pratica, qualcosa che avrei dovuto leggere molto tempo fa!
Berimbolo,

1

In realtà, tutto ciò è chiaramente descritto nei documenti Java (ma me ne sono reso conto solo dopo aver letto le risposte).

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

wait () - Il thread corrente deve possedere il monitor di questo oggetto. Il thread rilascia la proprietà di questo monitor e attende fino a quando un altro thread non notifica ai thread in attesa sul monitor di questo oggetto di riattivarsi tramite una chiamata al metodo di notifica o al metodo notifyAll. Il thread attende quindi fino a quando non riesce a ottenere nuovamente la proprietà del monitor e riprende l'esecuzione.

sleep () - Fa sospendere il thread attualmente in esecuzione (interrompe temporaneamente l'esecuzione) per il numero specificato di millisecondi, soggetto alla precisione e all'accuratezza dei timer e degli scheduler del sistema. Il thread non perde la proprietà di alcun monitor.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.