Thread.yield() считается вредным?
Во время работы над моим Java-приложением у меня есть простой многопоточный случай (один асинхронный поток загрузчика ресурсов и один основной поток, ожидающий завершения загрузчика, обновление пользовательского интерфейса с прогрессом), который я решил решить, позвонив
while( !foo.isInitialized() ) {
Thread.yield();
}
в основной теме. Я знаю, что есть более надежные решения; Тем не менее, загрузчик не создан мной, а это в основном библиотека только для чтения (я не могу просто wait()
, потому что я не могу заставить его отправить мне notify()
, а также не умереть после завершения), и мне просто нужно подождать, пока загрузка не будет выполнена.
Java doc говорит, что (обратите внимание, что это было not present в 1.6 документах и был добавлен 1.7 документами)
Редко использовать этот метод.
NetBeans предупреждает меня, что
Вызов метода yield()
on java.lang.Thread
обычно используется для маскировки проблем синхронизации и его следует избегать.
Google Codepro AnalytiX, OTOH, говорит
Метод Thread.yield()
не должен использоваться, потому что его поведение несовместимо на всех платформах.
Должен ли я быть связан с этими предупреждениями и пытаться найти лучшее решение (все предложения приветствуются), или я должен рассматривать их как "предупреждающий шум" и подавлять/игнорировать их?
Примечание. Я думал о очевидной возможности использования sleep()
(Являются ли ссылки на Thread.sleep(0) и Thread.yield() эквивалентными? Вот); все же, если yield
ing не имеет "бонуса" от постоянного сна, почему Java предоставляет его вообще - и каковы фактические действительные варианты использования для него?
Немного связаны:
Есть ли лучшее решение для Thread.yield()? и Thread.Sleep или Thread.Yield
Ответы
Ответ 1
Основная проблема с вызовом Thread.yield()
в цикле while без механики ожидания заключается в том, что он легко становится циклом ожидания ожидания, используя 100% одного из ваших ядер.
Если нет никаких других потоков для планирования, когда вы уступаете, полученный поток, вероятно, будет перепланирован очень быстро и, следовательно, приведет к высокому использованию процессора.
Кроме этого, в этом случае я не вижу, чтобы это было более вредно. Тем не менее, это довольно бессмысленно - если вы собираетесь писать цикл busy-wait, вы можете просто сделать while (!foo.isInitialized());
и избегать подчеркивания планировщика.
Что вам следует делать, если вы не можете иметь механизм уведомления, - это, по крайней мере, спать в цикле. Это позволит вашим процессорам немного отдохнуть.
Типичная реализация такого цикла:
while(!foo.isInitialized()) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return; // or handle some other way
}
}