Diferencia entre wait () y sleep ()


1204

¿Cuál es la diferencia entre a wait()y sleep()en Threads?

¿Entiendo que un wait()subproceso -ing todavía está en modo de ejecución y usa ciclos de CPU pero un sleep()-ing no consume ningún ciclo de CPU correcto?

¿Por qué tenemos ambos wait() y sleep(): cómo varía su implementación en un nivel inferior?


50
Muy buena pregunta. La semántica de ambos es fácil de confundir.
Andreas Petersson

1
Muy buenas preguntas pero son 2 en una. ¿Por qué tenemos ambos no es lo mismo que cómo se pueden implementar (y no se implementan) en un nivel inferior? También he respondido a eso.
estani

Supongamos que un subproceso A está en un bloque sincronizado, y mientras está en la CPU de este subproceso se toma y se entrega a otro subproceso B. Ahora, en qué estado irá el subproceso A, entrarán los otros subprocesos que esperan en este bloque sincronizado. ?
Peter

1
Aquí hay un buen artículo que lo describe: qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man

3
es EXACTAMENTE lo opuesto: el modo de suspensión "usa" todos sus ciclos de CPU disponibles, pero dado que el subproceso estará en "ESPERA", estos se pueden generar si es necesario; de hecho, la mayoría de los sistemas operativos producen automáticamente los ciclos SI es posible, por lo tanto su hilo no creará ninguna carga real de CPU ... sin embargo, lo hará en sistemas operativos más antiguos. Object.wait (), por otro lado, NUNCA usa ningún ciclo (sin ser notificado) porque eso se realiza a través de interrupciones de software en muchos casos: bloqueos privados, transitorios y transparentes, implementados por la JVM. Thread.sleep es una mala práctica.
specializt

Respuestas:


838

A waitpuede ser "despertado" por otro hilo que llama notifyal monitor que se está esperando mientras que a sleepno se puede. También un wait(y notify) debe suceder en un bloque synchronizeden el objeto del monitor, mientras sleepque no:

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

En este punto, el hilo actualmente en ejecución espera y libera el monitor . Otro hilo puede hacer

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

(en el mismo monobjeto) y el primer subproceso (suponiendo que sea el único subproceso que espera en el monitor) se activará.

También puede llamar notifyAllsi hay más de un hilo esperando en el monitor; esto los despertará a todos . Sin embargo, solo uno de los hilos podrá agarrar el monitor (recuerde que waitestá en un synchronizedbloque) y continuar; los demás se bloquearán hasta que puedan adquirir el bloqueo del monitor.

Otro punto es que usted llama waiten Objectsí mismo (es decir, espera en el monitor de un objeto), mientras que se llama sleepel Thread.

Sin embargo, otro punto es que se puede obtener activaciones falsas de wait(es decir, el hilo que está esperando hojas de vida sin razón aparente). Usted debe siempre waitmientras que hace girar en alguna condición de la siguiente manera:

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

131
No, no puede. Solo puede ser interrumpido.
Peter Štibraný

99
Cuando está interrumpiendo, debe saber qué hilo desea interrumpir. Cuando llame a notificar, solo necesita un objeto, y no le importa si hay algún otro hilo que 'espere' en este objeto. esperar / notificar se usa para la comunicación, mientras que dormir se usa para, ehm, dormir.
Peter Štibraný

28
@ Geek: ¿por qué en el mundo dice que wait () desperdicia los ciclos de CPU?
Robert Munteanu

25
La interrupción está pensada como un mecanismo para alentar suavemente a un hilo a dejar de funcionar por completo y cancelar las operaciones restantes. wait/ notifyse usan generalmente para esperar a que algún otro subproceso realice una tarea o para esperar hasta que se cumpla una determinada condición.
Louis Wasserman

13
Leí todas las respuestas, sin embargo, todavía me falta un poco de información. Muchas personas escribieron las definiciones del Javadoc y también el significado de las dos palabras en inglés, pero no veo ¿Por qué debería usar el sueño en lugar de esperar? ¿Cuál es el benchmarking y la diferencia de velocidad entre los dos? Si puedo hacer todo lo que puedo hacer con el sueño, ¿por qué debería elegir dormir?
Balazs Zsoldos

334

Una diferencia clave que aún no se menciona es que mientras duerme un Thread no libera los bloqueos que contiene, mientras que espera libera el bloqueo del objeto que wait()se activa.

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


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

105
La espera solo libera el bloqueo para el objeto al que llama wait (). No libera ninguna otra cerradura.
Jon Skeet

16
En realidad, no es necesario llamar a la suspensión desde dentro de una cerradura: las cerraduras y la espera / notificación van de la mano, pero las cerraduras y la suspensión no están relacionadas.
oxbow_lakes

77
@oxbow_lakes: diría que no debes dormir con cerraduras, hay pocos casos de uso para eso. Solo quería señalar las diferencias.
Robert Munteanu

55
@RobertMunteanu, su respuesta afirma engañosamente que sleeptiene bloqueos de Java , pero no lo hace. Para tener una comparación justa, compararíamos synchronized(OUTER_LOCK){ Thread.sleep(1000); }con synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }y podemos ver que ambas instrucciones no liberan el OUTER_LOCK. Si hay alguna diferencia, podemos decir que sleepno utiliza explícitamente los bloqueos de Java , pero la pregunta es acerca de la cita "¿cómo varía su implementación en un nivel inferior?" entre comillas
Pacerier

2
@Pacerier wait()está asociado con la condición del bloqueo más interno desde el que se llama, en su ejemplo de código, wait()solo se puede liberar LOCKy no OUTER_LOCK. Así es como el monitor Java está diseñado de todos modos. Una comparación justa sería synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }y synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. En este caso sleep()mantendrá ambas cerraduras mientras wait()se liberará LOCKpero aún se mantendráOUTER_LOCK
danze

244

Encontré esta publicación útil. Se pone la diferencia entre Thread.sleep(), Thread.yield()y Object.wait()en términos humanos. Citar:

Eventualmente, todo llega al programador del sistema operativo, que distribuye tiempos de espera a los procesos y subprocesos.

sleep(n)dice: "Terminé con mi parte de tiempo, y por favor no me des otro por al menos n milisegundos". El sistema operativo ni siquiera intenta programar el hilo dormido hasta que haya pasado el tiempo solicitado.

yield()dice "Ya terminé con mi tiempo, pero todavía tengo trabajo que hacer". El sistema operativo es libre de darle inmediatamente al hilo otro segmento de tiempo, o de dar algún otro hilo o procesar a la CPU que el hilo de rendimiento acaba de abandonar.

wait()dice: "Ya terminé con mi parte del tiempo". No me des otro tiempo hasta que alguien llame a notificar () ". Al igual que con sleep()el sistema operativo, ni siquiera intentará programar su tarea a menos que alguien llame notify()(o se produzca uno de los otros escenarios de activación).

Los subprocesos también pierden el resto de su segmento de tiempo cuando realizan el bloqueo de E / S y en algunas otras circunstancias. Si un subproceso funciona en todo el intervalo de tiempo, el sistema operativo toma el control por la fuerza aproximadamente como si se yield()hubiera llamado, para que otros procesos puedan ejecutarse.

Raramente lo necesita yield(), pero si tiene una aplicación computacional con límites de tareas lógicas, la inserción de una yield() podría mejorar la capacidad de respuesta del sistema (a expensas del tiempo; los cambios de contexto, incluso solo para el sistema operativo y viceversa, no son gratuitos). Mida y pruebe contra objetivos que le interesan, como siempre.


El rendimiento depende básicamente de la plataforma ... javamex.com/tutorials/threads/yield.shtml
Pacerier

la explicación de sleep(n)está implícitamente diciendo que el hilo actualmente en ejecución renuncia voluntariamente al monitor de la cerradura, lo cual no es cierto . Cita del javadoc de Thread : "El hilo no pierde la propiedad de ningún monitor".
Clint Eastwood

2
@Jonathan no se mencionan los monitores en la respuesta, y eso se debe a sleepque no tiene ningún comportamiento especial con respecto al monitor que cualquier otra llamada al método Java, es decir, no interactúa ni los modifica de ninguna manera. Si quisiera decir algo sobre los monitores, debe especificar que wait, además de lo dicho anteriormente, renuncie temporalmente al bloqueo del objeto al que se llama.
pqnet

¿Cómo funciona la notificación en el nivel del planificador del sistema operativo? ¿Notifica llamar a algún tipo de controlador de eventos con una identificación de subproceso particular, lo que permite al planificador volver a colocar el subproceso relevante en la cola en ejecución? También tengo otra pregunta, ¿dónde encaja el concepto de spinlock? ¿Sería relevante solo para dormir o esperar solo usar spinlock en el nivel muy bajo?
CMCDragonkai

@Erich, se utiliza wait(n)para comparar sleep(n). No tiene sentido comparar usando uno sin argumentos.
Pacerier

68

Aquí hay muchas respuestas, pero no pude encontrar la distinción semántica mencionada en ninguna.

No se trata del hilo en sí; ambos métodos son necesarios ya que admiten casos de uso muy diferentes.

sleep()envía el subproceso a dormir como estaba antes, solo empaqueta el contexto y deja de ejecutarse por un tiempo predefinido. Entonces, para despertarlo antes de tiempo, debe conocer la referencia de subproceso. Esta no es una situación común en un entorno multiproceso. Se utiliza principalmente para la sincronización de tiempo (por ejemplo, despertar en exactamente 3,5 segundos) y / o la imparcialidad codificada (solo duerme un rato y deja que otros hilos funcionen).

wait(), por el contrario, es un mecanismo de sincronización de hilo (o mensaje) que le permite notificar un hilo del cual no tiene referencia almacenada (ni cuidado). Puede pensarlo como un patrón de publicación-suscripción ( wait== suscribirse y notify()== publicar). Básicamente, utilizando la notificación () está enviando un mensaje (que incluso podría no recibirse y normalmente no le importa).

En resumen, normalmente se usa sleep()para sincronización de tiempo y wait()para sincronización de subprocesos múltiples.

Se podrían implementar de la misma manera en el sistema operativo subyacente, o en absoluto (ya que las versiones anteriores de Java no tenían multiprocesamiento real; probablemente algunas máquinas virtuales pequeñas tampoco lo hacen). No olvide que Java se ejecuta en una VM, por lo que su código se transformará en algo diferente de acuerdo con la VM / OS / HW en la que se ejecuta.


54

Aquí, he enumerado algunas diferencias importantes entre wait()y los sleep()métodos.
PD: También haga clic en los enlaces para ver el código de la biblioteca (funcionamiento interno, solo juegue un poco para comprenderlo mejor).

Espere()

  1. wait() El método libera el bloqueo.
  2. wait()Es el método de Objectclase.
  3. wait() es el método no estático public final void wait() throws InterruptedException { //...}
  4. wait()debe ser notificado por notify()o notifyAll()métodos.
  5. wait() El método debe llamarse desde un bucle para tratar la falsa alarma.

  6. wait() Se debe llamar al método desde el contexto sincronizado (es decir, el método o bloque sincronizado), de lo contrario arrojará IllegalMonitorStateException

dormir()

  1. sleep() El método no libera el bloqueo.
  2. sleep()Es el método de java.lang.Threadclase.
  3. sleep() es el método estático public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. después de la cantidad de tiempo especificada, sleep()se completa.
  5. sleep()mejor no llamar desde el bucle (es decir, ver el código a continuación ).
  6. sleep()Se puede llamar desde cualquier lugar. No hay requisitos específicos.

Ref: diferencia entre esperar y dormir

Fragmento de código para llamar al método de espera y suspensión

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

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

transición de hilo a diferentes estados de hilo


¿Es correcto que un hilo dormido pueda ser despertado por llamadas para notificar ()? Algunas de las otras publicaciones aquí parecen implicar que un hilo dormido no se puede despertar sino interrumpir.
berimbolo

Sí, Thread.sleep()se usa para hacer que el tiempo del procesador esté disponible para los otros hilos. el período de suspensión se puede terminar por interrupciones (es decir, por JVM). Lea este stackoverflow.com/questions/4264355/…
roottraveller

Esa publicación también dice interrupt () es lo que despierta un hilo dormido? Me refería al diagrama de estado del hilo que publicaste donde dice notificar o notificar a todos. Solo quiero asegurarme de que entiendo eso.
berimbolo

@berimbolo notify()o notifyAll()son Objectmétodos de clase. por lo tanto están disponibles serán obj de toda clase (es decir, aquí también con Threadclase). vea el código grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

2
OK Necesito leer más sobre la programación de subprocesos, ya que no puedo encontrar ejemplos de notify () o notifyAll () al despertar los hilos inactivos solo interrumpen () haciendo esto. Todos los ejemplos relacionan notify () y notifyAll () a subprocesos que esperan en algún objeto de monitor.
berimbolo

29

Hay algunas notas clave de diferencia que concluyo después de trabajar en esperar y dormir, primero eche un vistazo a la muestra usando wait () y sleep ():

Ejemplo1 : usando wait () y 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();
}

Deja en claro algunas notas clave:

  1. Llamar al :
    • wait (): llama al hilo actual que contiene el objeto HandObject
    • sleep (): Llamada al subproceso ejecutar tarea get beer (es un método de clase, por lo que afecta el subproceso actual)
  2. Sincronizado :
    • wait (): cuando se sincroniza el acceso a varios subprocesos al mismo objeto (HandObject) (cuando se necesita comunicación entre más de un subproceso (subproceso ejecutar codificación, subproceso ejecutar obtener cerveza) acceso en el mismo objeto HandObject)
    • sleep (): cuando la condición de espera para continuar se ejecuta (Esperando cerveza disponible)
  3. Hold lock :
    • wait (): suelta el bloqueo para que otro objeto tenga oportunidad de ejecutarse (HandObject es gratis, puedes hacer otro trabajo)
    • sleep (): mantener el bloqueo durante al menos t veces (o hasta que se interrumpa) (Mi trabajo aún no termina, continuaré manteniendo el bloqueo y esperando alguna condición para continuar)
  4. Condición de despertador :
    • esperar (): hasta que la llamada notifique (), notifique a Todos () desde el objeto
    • sleep (): hasta que al menos expire el tiempo o se interrumpa la llamada
  5. Y el último punto es usar cuando como estani indique:

normalmente usa sleep () para sincronización de tiempo y wait () para sincronización de subprocesos múltiples.

Por favor corrígeme si estoy equivocado.


26

Diferencia entre wait () y sleep ()

  • La diferencia fundamental es que wait()es de Objecty sleep()es un método estático de Thread.

  • La principal diferencia es que wait()libera el bloqueo mientras sleep()no libera ningún bloqueo mientras espera.

  • wait()se usa para la comunicación entre subprocesos, mientras que sleep()se usa para introducir una pausa en la ejecución, generalmente.

  • wait()debe llamarse desde dentro de sincronizar o de lo contrario obtenemos un IllegalMonitorStateException, mientras que sleep() puede llamarse en cualquier lugar.

  • Para volver a iniciar un hilo desde wait(), debe llamar notify()o notifyAll(). En cuanto sleep(),al hilo se inicia después de un intervalo de tiempo especificado.

Similitudes

  • Ambos hacen que el hilo actual pase al estado No ejecutable .
  • Ambos son métodos nativos .

18

Esta es una pregunta muy simple, porque ambos métodos tienen un uso totalmente diferente.

La principal diferencia es esperar para liberar el bloqueo o monitor mientras el modo de suspensión no libera ningún bloqueo o monitor mientras espera. La espera se utiliza para la comunicación entre subprocesos, mientras que la suspensión se usa para introducir la pausa en la ejecución.

Esta fue solo una explicación clara y básica, si desea más que eso, continúe leyendo.

En caso de wait()que el subproceso del método pase al estado de espera y no volverá automáticamente hasta que llamemos al notify()método (o notifyAll()si tiene más de un subproceso en estado de espera y desea activar todos esos subprocesos). Y se necesita una sincronización o bloqueo de objeto o clase de bloqueo para acceder a la wait()o notify()o notifyAll()métodos. Y una cosa más, el wait()método se usa para la comunicación entre subprocesos porque si un subproceso pasa a estado de espera, necesitará otro subproceso para activar ese subproceso.

Pero en este caso, sleep()es un método que se utiliza para mantener el proceso durante unos segundos o el tiempo que desea. Debido a que no es necesario para provocar alguna notify()o notifyAll()método para conseguir que de nuevo hilo. O no necesita ningún otro hilo para volver a llamar ese hilo. Como si quieres que algo suceda después de unos segundos, como en un juego después del turno del usuario, quieres que el usuario espere hasta que la computadora juegue, entonces puedes mencionar el sleep()método.

Y una diferencia más importante que se pregunta a menudo en las entrevistas: sleep()pertenece a la Threadclase y wait()pertenece a la Objectclase.

Estas son todas las diferencias entre sleep()y wait().

Y hay una similitud entre ambos métodos: ambos son una declaración verificada, por lo que debe intentar atrapar o lanzar para acceder a estos métodos.

Espero que esto ayude.


16

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

Thread.sleep()envía el subproceso actual al estado "No ejecutable" durante cierto tiempo. El hilo mantiene los monitores que ha adquirido, es decir, si el hilo está actualmente en un bloque o método sincronizado, ningún otro hilo puede ingresar a este bloque o método. Si llama otro hilo t.interrupt(), despertará el hilo dormido.

Tenga en cuenta que dormir es un método estático, lo que significa que siempre afecta al hilo actual (el que está ejecutando el método de suspensión). Un error común es llamar a t.sleep()donde t es un hilo diferente; incluso entonces, es el hilo actual el que dormirá, no el hilo t.

t.suspend()es obsoleto. Al usarlo, es posible detener un hilo que no sea el hilo actual. Un hilo suspendido mantiene todos sus monitores y, dado que este estado no es interrumpible, es propenso a un punto muerto.

object.wait()envía el subproceso actual al estado "No ejecutable" , como sleep(), pero con un giro. Wait se llama en un objeto, no en un hilo; llamamos a este objeto el "objeto de bloqueo". Antes de que lock.wait()se llame, el hilo actual debe sincronizarse en el objeto de bloqueo; wait() luego libera este bloqueo y agrega el hilo a la "lista de espera" asociada con el bloqueo. Más tarde, otro hilo puede sincronizarse en el mismo objeto de bloqueo y llamada lock.notify(). Esto despierta el hilo de espera original. Básicamente, wait()/ notify()es como sleep()/ interrupt(), solo el subproceso activo no necesita un puntero directo al subproceso inactivo, sino solo al objeto de bloqueo compartido.


14

Esperar y dormir son dos cosas diferentes:

  • En sleep()el hilo deja de funcionar durante la duración especificada.
  • En wait()el subproceso deja de funcionar hasta que el objeto que se está esperando es notificado, generalmente por otros subprocesos.

pero puedes interrumpir un hilo dormido. En ese caso, wait () es redundante de hecho, también desperdicia ciclos de CPU :-(
Geek

99
La espera no desperdicia los ciclos de la CPU.
Peter Štibraný

1
@ Peter - Creo que sí. Espera () su porción de ciclos de CPU y luego el sistema operativo le da los ciclos de CPU a otros subprocesos. Creo que esto podría depender del sistema operativo, no estoy seguro.
Geek

3
Sería una implementación muy pobre de wait () si desperdiciara los ciclos de la CPU. esperar / notificar se usa bastante para la comunicación entre hilos.
Peter Štibraný

2
@Pacerier las dos construcciones están destinadas a un propósito diferente. Si desea que un subproceso se detenga durante un período fijo de tiempo que usa sleep, si desea que se detenga hasta que una entrada provenga del otro que usa wait/ notify. interruptpretende ser una forma de señalar a un hilo que debe dejar de hacer lo que está haciendo y terminar. Se maneja sleep, waitpero también bloquea las funciones de E / S (y puede implementar funciones con el mismo comportamiento llamando al método Thread.interrupted()). En cuanto al rendimiento, las funciones generalmente están optimizadas para el objetivo para el que fueron diseñadas.
pqnet

11

sleepes un método de Thread, waites un método de Object, por lo que wait/notifyes una técnica de sincronización de datos compartidos en Java (usando monitor ), pero sleepes un método simple de subproceso para detenerse.


8

sleep () es un método que se utiliza para retener el proceso durante unos segundos o el tiempo que desea, pero en caso de que el hilo de método wait () pase al estado de espera y no volverá automáticamente hasta que llamemos a notify () o notifique a todos ().

La principal diferencia es que wait () libera el bloqueo o monitor mientras sleep () no libera ningún bloqueo o monitor mientras espera. La espera se usa para la comunicación entre subprocesos, mientras que la suspensión se usa para introducir la pausa en la ejecución, generalmente.

Thread.sleep () envía el hilo actual al estado "No ejecutable" durante cierto tiempo. El hilo mantiene los monitores que ha adquirido, es decir, si el hilo está actualmente en un bloque o método sincronizado, ningún otro hilo puede ingresar a este bloque o método. Si otro hilo llama a t.interrupt () despertará el hilo dormido. Tenga en cuenta que dormir es un método estático, lo que significa que siempre afecta al hilo actual (el que está ejecutando el método de suspensión). Un error común es llamar a t.sleep () donde t es un hilo diferente; incluso entonces, es el hilo actual el que dormirá, no el hilo t.

object.wait () envía el hilo actual al estado "No ejecutable", como sleep (), pero con un giro. Wait se llama en un objeto, no en un hilo; llamamos a este objeto el "objeto de bloqueo". Antes de llamar a lock.wait (), el hilo actual debe sincronizarse en el objeto de bloqueo; wait () luego libera este bloqueo y agrega el hilo a la "lista de espera" asociada con el bloqueo. Más tarde, otro hilo puede sincronizarse en el mismo objeto de bloqueo y llamar a lock.notify (). Esto despierta el hilo de espera original. Básicamente, wait () / notify () es como sleep () / interrupt (), solo el hilo activo no necesita un puntero directo al hilo dormido, sino solo al objeto de bloqueo compartido.

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

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

Deje categorizar todos los puntos anteriores:

Call on:

  • Espere(): llama a un objeto; El subproceso actual debe sincronizarse en el objeto de bloqueo.
  • sleep (): llama a un hilo; siempre ejecutando hilo actualmente.

Synchronized:

  • Espere(): cuando varios hilos sincronizados acceden al mismo objeto uno por uno.
  • sleep (): cuando se sincronizan varios subprocesos, espere el reposo del subproceso de dormir.

Hold lock:

  • Espere(): suelta el bloqueo para que otros objetos tengan la oportunidad de ejecutarse.
  • sleep (): mantenga el bloqueo durante al menos t veces si se especifica el tiempo de espera o alguien interrumpe.

Wake-up condition:

  • Espere(): hasta que la llamada notifique (), notifique a Todos () desde el objeto
  • sleep (): hasta que caduque al menos el tiempo o llame a interrupt ().

Usage:

  • dormir(): para sincronización horaria y;
  • wait (): para sincronización multihilo.

Ref: diff sleepywait


6

En palabras simples, esperar es esperar hasta que otro hilo lo invoque mientras que dormir es "no ejecutar la siguiente instrucción" durante un período de tiempo específico.

Además, el sueño es un método estático en la clase Thread y funciona en thread, mientras que wait () está en la clase Object y se llama a un objeto

Otro punto, cuando llama a wait en algún objeto, el hilo involucrado sincroniza el objeto y luego espera. :)


1
¿Por qué necesitas ambos? ¿Por qué dormir () no es suficiente?
Geek

2
Notificar se utiliza para la comunicación entre hilos. Para llamar a wait, necesitas algún objeto, sincronízalo y luego llama a wait. Para recibir una notificación, necesita otro hilo para sincronizar en el mismo objeto y llamar a notificar.
Peter Štibraný

6

waity los sleepmétodos son muy diferentes:

  • sleep no tiene forma de "despertar",
  • mientras que waittiene una forma de "despertar" durante el período de espera, por otro hilo llamando notifyo notifyAll.

Ahora que lo pienso, los nombres son confusos a ese respecto; sin embargo, sleepes un nombre estándar y waites como WaitForSingleObjecto WaitForMultipleObjectsen la API de Win.


3
Pero podemos interrumpir un sueño , ¿no? Entonces, ¿cuál es la diferencia con ese sueño / interrupción frente a esperar / notificar?
Pacerier

2
Puede interrumpir a una persona dormida, pero solo puede notificar a una persona que espera. Los hilos son iguales.
Rishi

5

De esta publicación: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

Método wait ().

1) El hilo que llama al método wait () libera el bloqueo que contiene.

2) El subproceso recupera el bloqueo después de que otros subprocesos llaman a los métodos notify () o notifyAll () en el mismo bloqueo.

3) el método wait () debe llamarse dentro del bloque sincronizado.

4) el método wait () siempre se llama a los objetos.

5) Los hilos en espera pueden ser despertados por otros hilos llamando a los métodos notify () o notifyAll ().

6) Para llamar al método wait (), el hilo debe tener bloqueo de objeto.

método sleep ()

1) El hilo que llama al método sleep () no libera el bloqueo que contiene.

2) el método sleep () se puede llamar dentro o fuera del bloque sincronizado.

3) el método sleep () siempre se llama en subprocesos.

4) Los hilos dormidos no pueden ser despertados por otros hilos. Si lo hace, el hilo arrojará la InterruptedException.

5) Para llamar al método sleep (), el hilo no necesita tener bloqueo de objeto.


4

Aquí wait () estará en el estado de espera hasta que lo notifique otro subproceso, pero where as sleep () tendrá algún tiempo ... después de eso se transferirá automáticamente al estado Ready ...


4
  1. wait()Es un método de Objectclase.
    sleep()Es un método de Threadclase.

  2. sleep()permite que el hilo pase al sleepestado por x milisegundos.
    Cuando un hilo entra en estado de suspensión it doesn’t release the lock.

  3. wait()permite que el hilo libere el bloqueo y goes to suspended state.
    Este hilo estará activo cuando se llame a un método notify()o notifAll()para el mismo objeto.


4

Una gran diferencia potencial entre dormir / interrumpir y esperar / notificar es que

Generar una excepción cuando no es necesario es ineficiente. Si tiene subprocesos que se comunican entre sí a una velocidad alta, generaría muchas excepciones si estuviera llamando a interrupción todo el tiempo, lo que es un desperdicio total de CPU.


+1, un punto válido en realidad, aunque discutir sobre los
aspectos

En otras palabras, la sobrecarga de crear excepciones podría ser significativamente menor que la sobrecarga de la implementación del sistema de uno frente al otro.
Pacerier

3

Tienes razón: Sleep () hace que ese subproceso se "duerma" y la CPU se apagará y procesará otros subprocesos (también conocidos como cambio de contexto), aunque creo que Wait mantiene a la CPU procesando el subproceso actual.

Tenemos ambos porque, aunque puede parecer sensato permitir que otras personas usen la CPU mientras no la está utilizando, en realidad hay una sobrecarga en el cambio de contexto; dependiendo de cuánto tiempo duerma, puede ser más costoso en los ciclos de la CPU para cambiar los hilos de lo que es simplemente hacer que su hilo no haga nada durante unos pocos ms.

También tenga en cuenta que el sueño fuerza un cambio de contexto.

Además, en general no es posible controlar el cambio de contexto, durante la espera, el sistema operativo puede (y esperará por más tiempo) elegir procesar otros hilos.


44
wait () no mantiene la CPU procesando el hilo actual. Es como dormir porque también causa un cambio de contexto: javamex.com/tutorials/threads/context_switch.shtml . He estado pidiendo durante medio año todo el stackoverflow y parece que nadie sabe cuál es la diferencia entre esperar / notificar vs dormir / interrumpir.
Pacerier

aunque la suspensión no mantiene a la CPU procesando el hilo actual, creo que de todos modos es un poco una carga para la CPU, porque la CPU necesita rastrear el momento de cuándo finalizar la suspensión. No tiene ese disparador externo como "notificar" en espera. ¿No?
Vladimir Nabokov

@VladimirNabokov, El disparador externo es interrupt. El tiempo final está nadentro wait(n). ¶¶ ¡Han pasado 8 años y todavía nadie tiene la respuesta!
Pacerier

3

Los métodos se usan para diferentes cosas.

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

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

Thread.sleep (n) puede interrumpirse, pero Object.wait () debe ser notificado. Es posible especificar el tiempo máximo de espera: Object.wait(5000)por lo que sería posible usarlo wait, er, sleeppero luego tienes que molestarte con las cerraduras.

Ninguno de los métodos utiliza la CPU mientras duerme / espera.

Los métodos se implementan usando código nativo, usando construcciones similares pero no de la misma manera.

Búsquelo usted mismo: ¿está disponible el código fuente de los métodos nativos? El archivo /src/share/vm/prims/jvm.cppes el punto de partida ...


El tiempo de Thread.sleep también se puede establecer en indefinido. Object.wait timing también se puede establecer en definitivo. Esta respuesta no explica por qué necesitamos 2 martillos que hagan lo mismo.
Pacerier

Thread.sleep(big_num) debe ser interrumpido Object.wait(small_num) puede ser notificado
Pacerier

3

Wait () y sleep () ¿Diferencias?

Thread.sleep () Una vez que se completa su trabajo, solo se libera el bloqueo para todos. hasta que nunca suelte la cerradura a nadie.

  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 () Cuando vaya a la etapa de espera, se soltará la tecla y esperará algunos segundos según el parámetro.

Por ejemplo:

si tomas el café con la mano derecha, puedes tomar otra persona de la misma mano, cuando la dejes, solo tomarás otro objeto del mismo tipo aquí. además. esto es dormir () tu hora de dormir no trabajaste, solo estás durmiendo ... lo mismo aquí también.

Espere(). cuando te desaniman y tomas otro significado mientras esperas, eso es esperar

estás jugando películas o cualquier cosa en tu sistema igual que el reproductor, no puedes jugar más de una a la vez, es aquí, cuando cierras y eliges otra película o canción de cualquier persona, mientras se llama esperar


3

waitlibera el bloqueo y sleepno lo hace. Un hilo en el estado de espera es elegible para despertarse tan pronto como sea notifyo notifyAllque se llama. Pero en caso de que sleepel hilo mantenga el bloqueo y solo será elegible una vez que termine el tiempo de suspensión.


Entonces, si el hilo está durmiendo durante 10 segundos y ocurre una excepción interrumpida ????
Geek

Se InterruptedExceptionlanza @Geek An , tal como se dice en el Javadoc.
Marqués de Lorne

@EJP: ¿Eres el mismo EJP que estaba en los foros de sun.java.com? Al menos su puntaje sugiere lo mismo :-)
Geek

2

sleep()El método hace que el subproceso actual pase del estado de ejecución al estado de bloqueo durante un tiempo especificado. Si el hilo actual tiene el bloqueo de cualquier objeto, entonces lo mantiene, lo que significa que otros hilos no pueden ejecutar ningún método sincronizado en ese objeto de clase.

wait() El método hace que el subproceso actual entre en estado de bloque durante un tiempo específico o hasta que se notifique, pero en este caso el subproceso libera el bloqueo del objeto (lo que significa que otros subprocesos pueden ejecutar cualquier método sincronizado del objeto que llama.


2

En mi opinión, la principal diferencia entre ambos mecanismos es que dormir / interrumpir es la forma más básica de manejar hilos, mientras que esperar / notificar es una abstracción destinada a facilitar la comunicación entre hilos. Esto significa que dormir / interrumpir puede hacer cualquier cosa, pero que esta tarea específica es más difícil de hacer.

¿Por qué esperar / notificar es más adecuado? Aquí hay algunas consideraciones personales:

  1. Hace cumplir la centralización. Permite coordinar la comunicación entre un grupo de hilos con un solo objeto compartido. Esto simplifica mucho el trabajo.

  2. Aplica la sincronización. Porque hace que el programador envuelva la llamada para esperar / notificar en un bloque sincronizado.

  3. Es independiente del origen y el número del hilo. Con este enfoque, puede agregar más subprocesos arbitrariamente sin editar los otros subprocesos o realizar un seguimiento de los existentes. Si usó dormir / interrumpir, primero necesitaría mantener las referencias a los hilos dormidos, y luego interrumpirlos uno por uno, a mano.

Un ejemplo de la vida real que es bueno para explicar esto es un restaurante clásico y el método que utiliza el personal para comunicarse entre ellos: los camareros dejan las solicitudes del cliente en un lugar central (un tablero de corcho, una mesa, etc.), suena una campana, y los trabajadores de la cocina vienen a tomar tales pedidos. Una vez que hay algún curso listo, el personal de la cocina vuelve a tocar el timbre para que los camareros estén al tanto y se los lleven a los clientes.


2

El ejemplo sobre el sueño no libera el bloqueo y la espera sí

Aquí hay dos clases:

  1. Principal : contiene el método principal y dos hilos.
  2. Singleton : esta es una clase singleton con dos métodos estáticos getInstance () y 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();
    
     }
    }

y

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;

 }
}

Ahora ejecute este ejemplo, obtendrá el siguiente resultado:

_instance :null
Both singleton are same

Aquí las instancias Singleton creadas por threadA y threadB son las mismas. Significa que threadB está esperando afuera hasta que threadA libere su bloqueo.

Ahora cambie Singleton.java comentando Thread.sleep (500); método y descomentar Singleton.class.wait (500); . Aquí por Singleton.class.wait (500); El método threadA liberará todos los bloqueos de adquisición y pasará al estado "No ejecutable", el threadB obtendrá el cambio para ingresar en el bloque sincronizado.

Ahora corre de nuevo:

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

Aquí las instancias Singleton creadas por threadA y threadB NO son las mismas debido a que threadB consiguió un cambio para ingresar en el bloque sincronizado y después de 500 milisegundos, threadA comenzó desde su última posición y creó un objeto Singleton más.


2

Debe llamarse desde el bloque sincronizado: el wait() método siempre se llama desde el bloque sincronizado, es decir, el wait()método debe bloquear el monitor de objetos antes del objeto en el que se llama. Pero el sleep()método se puede llamar desde un bloque sincronizado externo, es decir, el sleep()método no necesita ningún monitor de objetos.

IllegalMonitorStateException: si wait()se llama al método sin adquirir el bloqueo del objeto que IllegalMonitorStateExceptionse lanza en tiempo de ejecución, pero el sleep()método nunca arroja dicha excepción.

Pertenece a qué clase: el wait() método pertenece a la java.lang.Objectclase pero el sleep()método pertenece a la java.lang.Threadclase.

Llamado en objeto o hilo: el wait() método se llama en objetos pero el sleep()método se llama en hilos, no en objetos.

Estado Tema: cuando wait()se llama al método de objeto, subproceso de supervisión de dicho objeto Holded pasa de correr a estado de espera y puede volver al estado ejecutable sólo cuando notify()o notifyAll()método que se llama en ese objeto. Y luego, el planificador de subprocesos programa ese subproceso para pasar del estado ejecutable al estado en ejecución. cuando sleep()se llama en el subproceso, pasa del estado de ejecución al estado de espera y puede volver al estado de ejecución cuando el tiempo de inactividad se ha agotado.

Cuando se llama desde un bloque sincronizado: cuando wait()se llama al método, el hilo deja el bloqueo del objeto. Pero el sleep()método cuando se llama desde el bloque sincronizado o el hilo del método no deja el bloqueo del objeto.

Para más referencia


probablemente una mejor URL de referencia que esa.
Dibujó el

2

Desde la página de documentación de Oracle en el método wait () de Object:

public final void wait()
  1. Hace que el hilo actual espere hasta que otro hilo invoque el notify()método o el notifyAll()método para este objeto. En otras palabras, este método se comporta exactamente como si simplemente realizara la llamada wait(0).
  2. El hilo actual debe poseer el monitor de este objeto. El subproceso libera la propiedad de este monitor y espera hasta que otro subproceso notifique a los subprocesos que esperan que el monitor de este objeto se active
  3. son posibles interrupciones y despertares espurios
  4. Este método solo debe ser llamado por un subproceso que sea el propietario del monitor de este objeto

Este método arroja

  1. IllegalMonitorStateException - si el hilo actual no es el propietario del monitor del objeto.

  2. InterruptedException- si algún hilo interrumpió el hilo actual antes o mientras el hilo actual estaba esperando una notificación. El estado interrumpido del hilo actual se borra cuando se lanza esta excepción.

Desde la página de documentación de Oracle sobre el método de clase sleep ()Thread :

public static void sleep(long millis)
  1. Hace que el subproceso que se está ejecutando actualmente se suspenda (cesa temporalmente la ejecución) durante el número especificado de milisegundos, sujeto a la precisión y exactitud de los temporizadores y programadores del sistema.
  2. El hilo no pierde la propiedad de ningún monitor.

Este método arroja:

  1. IllegalArgumentException - si el valor de millis es negativo

  2. InterruptedException- si algún hilo ha interrumpido el hilo actual. El estado interrumpido del hilo actual se borra cuando se lanza esta excepción.

Otra diferencia clave:

wait()es un método no estático (método de instancia) a diferencia del método estático sleep()(método de clase).


1

wait()se proporciona dentro de un método sincronizado, mientras que sleep()se proporciona dentro de un método no sincronizado porque el wait()método libera el bloqueo del objeto pero sleep()o yield()libera el lock().


sleep()puede estar dentro de un synchronizedbloque o método. La respuesta no explica nada.
Marqués de Lorne

1
  • El método wait(1000)hace que el hilo actual duerma hasta un segundo .
    • Un hilo podía dormir menos de 1 segundo si recibe el notify()onotifyAll() llamada al método.
  • La llamada a sleep(1000)hace que el subproceso actual se suspenda durante exactamente 1 segundo .
    • Además, el hilo dormido no mantiene bloqueado ningún recurso . Pero el hilo de espera sí.

1
sleep(1000)no garantiza dormir por exactamente 1 segundo. Puede ser interrumpido antes.
Lucio

1
Estas publicaciones son muy confusas. Todas las otras publicaciones en este hilo dicen que un hilo dormido SOS mantiene el bloqueo y que un hilo en espera NO mantiene el bloqueo. Del mismo modo, la publicación con el diagrama implica que las llamadas para notificar () despiertan los hilos dormidos, pero otras publicaciones (y los diagramas de estado de los hilos) implican que solo la interrupción () o el período de tiempo de espera pasan. Acabo de pedirme una copia de concurrencia de Java en la práctica, ¡algo que debería haber leído hace mucho tiempo!
berimbolo

1

En realidad, todo esto se describe claramente en los documentos de Java (pero me di cuenta de esto solo después de leer las respuestas).

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

wait (): el subproceso actual debe ser el propietario del monitor de este objeto. El subproceso libera la propiedad de este monitor y espera hasta que otro subproceso notifique a los subprocesos que esperan en el monitor de este objeto para que se activen mediante una llamada al método de notificación o al método de notificación completa. El subproceso luego espera hasta que pueda volver a obtener la propiedad del monitor y reanude la ejecución.

sleep (): hace que el subproceso que se está ejecutando actualmente se suspenda (cesa temporalmente la ejecución) durante el número especificado de milisegundos, sujeto a la precisión y exactitud de los temporizadores y programadores del sistema. El hilo no pierde la propiedad de ningún monitor.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.