Java & Threads: прерванные исключения и как правильно использовать метод take () BlockingQueue - PullRequest
3 голосов
/ 14 июля 2009

Что именно происходит, когда в очереди ничего нет и вызывается метод take (). API говорит, что метод будет ждать, но означает ли это, что процессор вращается, проверяя наличие пустого / не пустого, пока элемент не окажется в очереди, или это означает, что поток завершает работу и будет вызван прерыванием? Если это относится к первому, я, вероятно, хотел бы увидеть, пуста ли очередь и вызывается ли она thread.yield (), чтобы оставить процессорное время. Мой вопрос действительно должен ли я вызывать yield или какой-то внутренний механизм обрабатывает это для меня?

Во-вторых, для чего предназначено прерванное исключение? Если я правильно понимаю, это означает, что если поток A выполняет этот метод и ожидает ввода, а другой поток B вызывает threadA.interrupt (), то поток A перехватит прерванное исключение и предположительно приостановит выполнение, если это хорошо. Это правильный образ мышления?

Ответы [ 3 ]

5 голосов
/ 14 июля 2009

Обратите внимание, что BlockingQueue является интерфейсом. Итак, то, что следует, зависит от реализации. Если вы посмотрите на исходный код для (скажем) LinkedBlockingQueue , источник для take () вызывает метод lockInterruptibly () для RentrantLock. Из документа для этого:

Если блокировка недоступна, тогда текущий поток становится недоступным для цели и ложь планирования потоков дремлющий до одной из двух вещей случается:

* The lock is acquired by the current thread; or
* Some other thread interrupts the current thread, and interruption of

поддерживается захват блокировки.

Я подозреваю, что происходит какое-то wait()/notify() или подобное. Будет ли вращаться процессор? Нет (проверьте через top или аналогичный)

Re. на ваш вопрос о прерываниях в бюллетене Java Specialist была очень интересная статья о interrupt() и о ловле / обработке InterruptedException.

Прочитайте статью, но, по сути, если вы поймаете исключение, вы будете прерывать:

  try {
        Thread.sleep(1000);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt(); // very important
        break;
      }
4 голосов
/ 14 июля 2009

Вызов wait () не вращается, обычно он использует службы ОС для ожидания события / условия - что переводит поток в спящий режим до тех пор, пока условие / событие не будет снова сигнализировано. Время ожидания процессора не используется.

Обычно вы получаете прерванное исключение, если поток блокирует вызов wait (), а другой поток вызывает interrupt () в этом блокирующем потоке, как вы и сказали.

0 голосов
/ 14 июля 2009

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

Прерывания - это безопасный способ сообщить нити, что вы хотите что-то от нее - прекратить обработку, проснуться и ответить на что-то и т. Д.

В общем, эти вещи зависят от ваших конкретных сценариев. В Java есть несколько приятных особенностей параллелизма, которые могут быть более применимы к ситуации.

...