Перейти к основному содержимому

Краткое введение в Java Thread.yield()

· 3 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим метод yield() в классе Thread .

Мы сравним его с другими идиомами параллелизма, доступными в Java, и в конечном итоге рассмотрим его практическое применение.

2. Краткий обзор доходности ()

Как следует из официальной документации, yield() предоставляет механизм для информирования «планировщика» о том, что текущий поток готов отказаться от своего текущего использования процессора, но хотел бы вернуться в расписание как можно скорее.

«Планировщик» может придерживаться или игнорировать эту информацию и фактически ведет себя по-разному в зависимости от операционной системы.

Следующий фрагмент кода отображает два потока с одинаковым приоритетом, уступающие после каждого расписания:

public class ThreadYield {
public static void main(String[] args) {
Runnable r = () -> {
int counter = 0;
while (counter < 2) {
System.out.println(Thread.currentThread()
.getName());
counter++;
Thread.yield();
}
};
new Thread(r).start();
new Thread(r).start();
}
}

Когда мы пытаемся запустить вышеуказанную программу несколько раз, мы получаем разные результаты; некоторые из них упомянуты ниже:

Запуск 1:

Thread-0
Thread-1
Thread-1
Thread-0

Запуск 2:

Thread-0
Thread-0
Thread-1
Thread-1

Итак, как вы можете видеть, поведение yield() недетерминировано и также зависит от платформы.

3. Сравнение с другими идиомами

Существуют и другие конструкции для воздействия на относительную последовательность потоков. Они включают в себя wait() , notify( ) и notifyAll() как часть класса Object , join() как часть класса Thread и sleep() как часть класса Thread .

Давайте посмотрим, как они соотносятся с yield() .

3.1. выход () против ожидания ()

  • В то время как yield() вызывается в контексте текущего потока, wait() может вызываться только для явно полученной блокировки внутри синхронизированного блока или метода.
  • В отличие от yield() , для wait () можно указать минимальный период времени ожидания перед любой попыткой снова запланировать поток.
  • С помощью wait() также можно разбудить поток в любое время с помощью вызова notify( ) или notifyAll() для соответствующего объекта блокировки.

3.2. выход () против сна ()

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

3.3. выход () против присоединиться ()

  • Текущий поток может вызывать join() в любом другом потоке, что заставляет текущий поток ждать, пока другой поток не умрет, прежде чем продолжить.
  • При желании он может указать период времени в качестве своего параметра, который указывает максимальное время, в течение которого текущий поток должен ждать, прежде чем возобновить работу.

4. Использование для yield()

Как следует из официальной документации, использовать yield() редко необходимо, и, следовательно, его следует избегать, если не совсем ясно с целями в свете его поведения.

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

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

5. Вывод

В этой краткой статье мы обсудили метод yield() в классе Thread и рассмотрели его поведение и ограничения в фрагменте кода.

Мы также изучили его сравнение с другими идиомами параллелизма, доступными в Java, и, наконец, рассмотрели некоторые варианты использования, где yield() может быть полезен.

Как всегда, вы можете ознакомиться с примерами, представленными в этой статье , на GitHub .