Подтвердить что ты не робот

Имеются ли выражения Thread.sleep(0) и Thread.yield()?

Являются ли эти два утверждения эквивалентными?

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

Ответ 1

Нет. Наиболее очевидным отличием является то, что sleep() выбрасывает (отмечен) InterruptedException. На практике эффект может быть почти таким же, но он полностью зависит от реализации.

Я бы сделал ставку на то, что каждый миллион раз подряд потребуется намного больше времени для sleep(), поскольку размерность системного таймера, вероятно, часто заставляет его фактически спать в течение незначительного времени.

Ответ 2

Выход добавляет текущий поток в готовую очередь и позволяет запускать другие потоки. Сон не гарантирует отказ от процессора.

Ответ 3

Это действительно зависит от платформы и версии JVM. Например, под Windows в JDK 5 (Hotspot), yield() буквально реализуется как Sleep (0) - хотя сон 0 обрабатывается слегка специально Windows, как я помню. Но в JDK 6 yield() реализуется как SwitchToThread().

Я собрал некоторую информацию некоторое время назад на Thread.yield(), включая некоторые детали реализации, которые могут представлять интерес. (Возможно, вам также захочется увидеть материал на Thread.sleep() Я собрал на том же сайте.)

Ответ 4

yield() сообщает планировщику потоков JVM что это нормально, чтобы дать другим потокам временные срезы. Обычно JVM использует это вызов для активации другого потока тот же приоритет потока. В хорошем превентивная многопоточная среда, yield() - нет-op. Однако это важно в кооперативе многопоточность, поскольку без yield(), один поток может съесть весь процессор.

sleep (x) сообщает JVM Thread Планировщик активно помещает эту нить спать и не запускать его снова, пока не менее x миллисекунд.

Ни sleep(), ни yield() не изменяются ничего о статусе синхронизаторы. Если ваша нить имеет замок, и вы вызываете сон (1000), то по крайней мере вторая пройдет прежде чем ваша нить просыпается. Когда это просыпается, он может решить освободить заблокировать - или он может удержать его больше.

ИСТОЧНИК: http://www.jguru.com/faq/view.jsp?EID=425624

Ответ 5

Источник OpenJDK (Java SE 7) имеет следующую реализацию для Thread.sleep(0) в JVM_Sleep функции 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);
    }
  }

И реализация Thread.yield() имеет следующий код:

  // 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();
  }

Так что Thread.sleep(0) и Thread.yield() могут вызывать одни и те же системные вызовы на некоторых платформах.

os::sleep и os::yield являются специфичными для платформы. На Linux и Windows: os::yield кажется намного проще, чем os::sleep. Например: os::yield вызовов Linux только sched_yield(). И os::sleep имеют около 70 строк кода.

Ответ 6

Известная книга Брайана Гетца "Java Concurrency in Practice" (опубликованная в 2006 году, но по-прежнему принципиально обоснованная) говорит следующее по этому вопросу.

Семантика Thread.yield и Thread.sleep(0) undefined [JLS17.9]; JVM может свободно реализовать их как no-ops или рассматривать их как подсказки планирования. В частности, им не требуется иметь семантику сна (0) в Unix-системах - поместить текущий поток в конец очереди выполнения для этого приоритета, уступая другим потокам с одним и тем же приоритетом, хотя некоторые JVM реализуют выход в сюда.

Остальное можно найти на страницах Javadoc.

Ответ 7

Thread.Yield может отказаться от ресурсов ЦП к потокам с более низкими приоритетами, тогда как Thread.Sleep(0) отказывается от CPU только для потоков с равными или более высокими приоритетами.

По крайней мере, на платформе Windows:)

Ответ 8

Thread.sleep() и Thread.yield() делают то же самое, за исключением того, что Thread.yield() отказывается только от потоков работающий на одном процессоре в многопроцессорной среде.

Ответ 9

Thread.Sleep() имеет несколько большие накладные расходы, поскольку он создает систему, которая включает в себя какой-то таймер, который пробудит процесс. (Зависит от реализации в основном)
В конце он в конце будет называть Yield().

Thread.Yield() Будет просто отказаться от поворота потока и получить его в следующем раунде.

Thread.Sleep(0) может иметь оптимизацию, чтобы просто вызвать доходность. (Опять же, реализация)

Ответ 10

Предполагается, что нужно сделать yield() - сделать текущую текущую нить вернитесь назад к runnable, чтобы другие потоки с одинаковым приоритетом получить свою очередь. Таким образом, мы намерены использовать yield() для содействия грациозному поворот среди нитей с равным приоритетом. В действительности, однако, yield() не гарантирует того, что он утверждает, и даже если yield() действительно приводит к тому, что нить перестает работать и обратно невозможно гарантировать, что доходная нить не будет снова выбрал всех остальных! Поэтому, хотя yield() может и часто do-make работающий поток отбрасывает свой слот на другой runnable thread с тем же приоритетом, нет никакой гарантии.

A yield() никогда не заставит поток перейти к ожиданию/спящему/ блокирующего состояния. В лучшем случае выход() приведет к тому, что поток будет бегущий к runnable, но опять же, он может вообще не иметь никакого эффекта.

Источник: SCJP Sun Certified Programmer book

Ответ 11

Это зависит от платформы и реализации, и они, вероятно, не эквивалентны.

В приведенном ниже фрагменте при использовании Thread.sleep(0) большую часть времени выдает результат:

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

В то время как при использовании Thread.yield(), в основном дает:

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

Смотрите фрагмент ниже:

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();
}

Ответ 12

Нет, они не эквивалентны и, кроме объяснений выше, Я считаю необходимым проверить Javadoc yield. Не рекомендуется использовать yield, если ниже ситуация не встречается.

 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.