tutorialspoint threads thread que multithread multi manage implement example java multithreading

threads - runnable java



¿Son equivalentes las sentencias Thread.sleep(0) y Thread.yield()? (12)

¿Son estas dos declaraciones equivalentes?

Thread.sleep(0); Thread.yield();


Lo que se supone que debe hacer el rendimiento () es hacer que el hilo actualmente en ejecución vuelva a ser ejecutable para permitir que otros hilos de la misma prioridad obtengan su turno. Entonces, la intención es usar yield () para promover giros elegantes entre subprocesos de prioridad igual. En realidad, sin embargo, no se garantiza que el método yield () haga lo que dice, e incluso si yield () hace que un hilo deje de ejecutarse y regrese a ejecutable, no hay garantía de que el hilo productivo no solo ser elegido de nuevo sobre todos los demás! Por lo tanto, aunque yield () podría (y a menudo lo hace) hacer que un hilo en ejecución ceda su ranura a otro hilo ejecutable de la misma prioridad, no hay garantía.

Un rendimiento () nunca hará que un hilo pase al estado de espera / suspensión / bloqueo. A lo sumo, un rendimiento () hará que un subproceso pase de ejecutable a ejecutable, pero nuevamente, podría no tener ningún efecto.

Fuente: SCJP Sun Certified Programmer book


yield () le dice al Programador de subprocesos de JVM que está bien darle a otros subprocesos segmentos de tiempo. Por lo general, la JVM usa esta llamada para activar otra cadena de la misma prioridad de subprocesos. En un buen entorno preventivo multithreading, yield () es un no-op. Sin embargo, es importante en un entorno cooperativo multihilo, ya que sin yield (), un hilo puede consumir toda la CPU.

sleep (x) le dice al Programador de subprocesos de JVM que active este subproceso y no lo vuelva a ejecutar hasta que hayan transcurrido al menos x milisegundos.

Ni sleep () ni yield () cambian nada sobre el estado de los bloqueos de sincronización. Si su hilo tiene un bloqueo, y llama a dormir (1000), al menos pasará un segundo antes de que su hilo se despierte. Cuando se despierta, puede decidir liberar el bloqueo, o puede retenerlo por más tiempo.

FUENTE: http://www.jguru.com/faq/view.jsp?EID=425624


El famoso libro de Brian Goetz, "Concurrencia de Java en la práctica" (publicado en 2006 pero aún fundamentalmente válido) dice lo siguiente sobre esta cuestión.

La semántica de Thread.yield y Thread.sleep (0) no está definida [JLS17.9]; la JVM es libre de implementarlos como no operativos o tratarlos como sugerencias de programación. En particular, no es necesario que tengan la semántica de suspensión (0) en sistemas Unix: coloque el hilo actual al final de la cola de ejecución para esa prioridad, cediendo a otros hilos de la misma prioridad, aunque algunas JVM implementan rendimiento en de esta manera.

El resto se puede encontrar en las páginas de Javadoc.


El rendimiento agrega el hilo actual a la lista de espera y permite que se ejecuten otros hilos. No se garantiza la suspensión de la CPU.


Es dependiente de la plataforma y la implementación, y es probable que no sean equivalentes.

El siguiente fragmento, cuando se utiliza Thread.sleep (0), la mayoría de las veces da el resultado:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Mientras que al usar Thread.yield (), en su mayoría da:

[0, 1, 1, 1, 1, 1, 1, 1, 1, 1] [0, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Ver el fragmento a continuación:

public class CompareSleepZeroAndYield { private ArrayList<Integer> list1 = new ArrayList<>(); private ArrayList<Integer> list2 = new ArrayList<>(); public ArrayList<Integer> getList1() { return list1; } public ArrayList<Integer> getList2() { return list2; } public CompareSleepZeroAndYield() { list1.add(0); list2.add(0); } public void tryFieldLock1() { synchronized (this.list1) { list1.add(list2.get(list2.size() - 1) + 1); } } public void tryFieldLock2() { synchronized (this.list2) { list2.add(list1.get(list1.size() - 1) + 1); } } public static void main(String[] args) { CompareSleepZeroAndYield obj = new CompareSleepZeroAndYield(); Thread t1 = new Thread(new Runnable() { @Override public void run() { int count = 10; while (--count >0) { obj.tryFieldLock1(); try { Thread.sleep(0); } catch (InterruptedException e) { e.printStackTrace(); } // compare above and below // Thread.yield() } System.out.println(obj.getList1()); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { int count = 10; while (--count >0) { obj.tryFieldLock2(); try { Thread.sleep(0); } catch (InterruptedException e) { e.printStackTrace(); } // compare above and below // Thread.yield() } System.out.println(obj.getList2()); } }); t1.start(); t2.start(); }


Esto realmente depende de la plataforma y la versión de la JVM. Por ejemplo, en Windows en JDK 5 (Hotspot), yield () se implementa literalmente como Sleep (0), aunque un sueño de 0 es tratado de forma muy especial por Windows, como recuerdo. Pero en JDK 6, yield () se implementa como SwitchToThread ().

Thread.yield() algo de información hace un tiempo en Thread.yield() , que incluye algunos detalles de implementación que pueden ser de interés. (También es posible que desee ver las cosas en Thread.sleep() que Thread.sleep() en el mismo sitio).


La fuente OpenJDK (Java SE 7) tiene la siguiente implementación para Thread.sleep(0) en la función JVM_Sleep de jvm.cpp:

if (millis == 0) { // When ConvertSleepToYield is on, this matches the classic VM implementation of // JVM_Sleep. Critical for similar threading behaviour (Win32) // It appears that in certain GUI contexts, it may be beneficial to do a short sleep // for SOLARIS if (ConvertSleepToYield) { os::yield(); } else { ThreadState old_state = thread->osthread()->get_state(); thread->osthread()->set_state(SLEEPING); os::sleep(thread, MinSleepInterval, false); thread->osthread()->set_state(old_state); } }

Y la implementación de Thread.yield () tiene el siguiente código:

// When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // Critical for similar threading behaviour if (ConvertYieldToSleep) { os::sleep(thread, MinSleepInterval, false); } else { os::yield(); }

De modo que Thread.sleep(0) y Thread.yield() pueden llamar a las mismas llamadas del sistema en algunas plataformas.

os::sleep y os::yield son cosas específicas de la plataforma. Tanto en Linux como en Windows: os::yield parece ser mucho más simple que os::sleep . Por ejemplo: os::yield de las llamadas a Linux solo sched_yield() . Y os::sleep tiene alrededor de 70 líneas de código.


No, no son equivalentes y además de las explicaciones anteriores, creo que es necesario verificar el Javadoc de yield . No parece una buena idea usar el yield menos que se encuentre la situación siguiente.

It is rarely appropriate to use this method. It may be useful for debugging or testing purposes, where it may help to reproduce bugs due to race conditions. It may also be useful when designing concurrency control constructs such as the ones in the {@link java.util.concurrent.locks} package.


No. La diferencia más obvia es que sleep() lanza la ( InterruptedException ) InterruptedException . En la práctica, el efecto puede ser casi el mismo, pero depende por completo de la implementación.

Apostaría a que hacer cada millón de veces seguidas llevaría mucho más tiempo para dormir (), ya que la granularidad del temporizador del sistema probablemente a menudo hace que duerma realmente durante un tiempo no despreciable.


Thread.Yield puede ceder el recurso de la CPU a hilos con prioridades más bajas, mientras que Thread.Sleep (0) abandona la CPU solo a hilos con prioridades iguales o superiores.

Al menos en la plataforma de Windows :)


Thread.Sleep() tiene una sobrecarga ligeramente mayor porque crea un sistema que incluye algún tipo de temporizador que activará el proceso. (Depende de la implementación básicamente)
En pocas palabras llamará un Yield() al final.

Thread.Yield() Simplemente abandonará el giro del hilo y lo ganará en la siguiente ronda.

Thread.Sleep(0) podría tener una optimización para simplemente llamar a yield. (Nuevamente, implementación)


Thread.sleep () y Thread.yield () hacen lo mismo, excepto que Thread.yield () renuncia solo a los hilos que se ejecutan en el mismo procesador en el entorno multiprocesador.