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

Реализация Thread.sleep()

Сегодня у меня было интервью, на котором я задал кандидату довольно обычный и основной вопрос о разнице между Thread.sleep() и Object.wait(). Я ожидал, что он ответит на что-то вроде как это, но он сказал, что эти методы в основном одно и то же, и, скорее всего, Thread.sleep использует Object.wait() внутри него, но sleep сам по себе не требует внешней блокировки. Это не совсем правильный ответ, потому что в JDK 1.6 этот метод имеет следующую подпись.

public static native void sleep(long millis) throws InterruptedException;

Но моя вторая мысль заключалась в том, что это не так уж смешно. Для достижения такого же эффекта можно использовать временное ожидание. Взгляните на следующий фрагмент кода:

public class Thread implements Runnable {
       private final Object sleepLock = new Object();

     // other implementation details are skipped

       public static void sleep(long millis) throws InterruptedException {
            synchronized (getCurrentThread().sleepLock){
                getCurrentThread().sleepLock.wait(millis);
            }
        }

В этом случае sleepLock - это объект, который используется, в частности, для блока синхронизации внутри метода sleep. Я предполагаю, что инженеры Sun/Oracle знают о бритве Occam, поэтому sleep имеет встроенную реализацию специально, поэтому мой вопрос в том, почему он использует собственные вызовы.

Единственная идея, которую я придумал, - это предположение, что кто-то может найти полезный вызов, например Thread.sleep(0). Это имеет смысл для управления планировщиком в соответствии с в этой статье:

Это имеет особый эффект очистки текущего кванта потока и перевода его в конец очереди на уровень приоритета. Другими словами, все запущенные потоки с одним и тем же приоритетом (и с более высоким приоритетом) получат возможность запускать до того, как заданный поток станет следующим заданным временем процессора.

Таким образом, блок synchronized даст ненужные накладные расходы.

Знаете ли вы какие-либо другие причины не использовать время ожидания в Thread.sleep() реализации?

4b9b3361

Ответ 1

Можно легко сказать, что Оккам Бритва режет другой путь. Предполагается, что стандартная/ожидаемая реализация JVM, лежащая в основе JDK, часто связывает "потоки" Java с собственными потоками, и включение потока в сон является фундаментальной функцией базовой платформы. Зачем переопределять его в java, если код потока в любом случае будет родным? Самое простое решение - использовать функцию, которая уже существует.

Некоторые другие соображения: Неоспоримая синхронизация незначительна в современных JVM, но это не всегда так. Раньше это была довольно "дорогая" операция по приобретению этого объектного монитора.

Если вы реализуете спящий поток внутри java-кода и способ, которым вы его реализуете, также не привязывается к ожиданию собственного потока, операционная система должна продолжать планировать этот поток, чтобы запустить код, который проверяет, будет ли это время пробуждать вверх. Как было сказано в комментариях, это, очевидно, не соответствует вашему примеру на современной JVM, но трудно сказать 1) то, что могло быть на месте и ожидалось в то время, когда класс Thread был указан таким образом. а также 2) Если это утверждение работает для каждой платформы, возможно, когда-либо захотелось реализовать JVM.

Ответ 2

Знаете ли вы какие-либо другие причины не использовать время ожидания в Thread.sleep() выполнении?

Поскольку библиотеки собственных потоков обеспечивают превосходную функцию ожидания: http://www.gnu.org/software/libc/manual/html_node/Sleeping.html

Чтобы понять, почему важные потоки важны, начинайте с http://java.sun.com/docs/hotspot/threads/threads.html

Версия 1.1 основана на зеленых потоках и не рассматривается здесь. Зеленые потоки имитируют потоки внутри виртуальной машины и использовались до перехода на собственную модель потоковой ОС в 1.2 и более поздних версиях. Зеленые потоки, возможно, имели преимущество в Linux в какой-то момент (так как вам не нужно создавать процесс для каждого собственного потока), но технология VM значительно продвинулась с версии 1.1, и все преимущества зеленых потоков, которые в прошлом были удалены производительность растет с годами.

Ответ 3

Thread.sleep() не будет пробужден раньше побочных пробуждений. Если вы используете Object.wait(), чтобы сделать это правильно (т.е. Убедитесь, что вы достаточно долгое время ожидания), вам понадобится цикл с запросом на прошедшее время (например, System.currentTimeMillis()), чтобы убедиться, что вы достаточно подождали.

Технически вы могли бы достичь той же функциональности Thread.sleep() с Object.wait(), но вам нужно будет написать больше кода, чтобы сделать это правильно.

Это является также актуальным и полезным обсуждением.