2013-05-22 3 views
1

Я использую BlockingQueue (LinkedBlockingQueue) для синхронизации данных между несколькими потоками. См. Рисунок ниже.Java BlockingQueue заставляет потоки ждать без необходимости.

Основной поток - производитель, который производит объекты, а затем помещает их в очередь каждого потребителя (поток 2-10). Необходимо подчеркнуть, что у каждого потребителя есть своя очередь, и каждый созданный объект будет иметь все очереди потребителей.

Производитель работает намного быстрее, чем потребители, поэтому мы можем предположить, что очередь не должна быть пустой во время прогона потребителей. Производитель будет заблокирован, когда очередь потребителя достигнет своей емкости (put() используется Продюсером). Потребитель берет объекты из очереди, используя take().

С этой настройкой я предполагаю, что потребитель будет редко (если вообще возможно) ожидать очереди, пока очередь пуста. Однако из приведенного ниже рисунка я вижу, что время от времени все Потребители должны ждать в очереди, чтобы они были заполнены объектами; во время ожидания я вижу, что производитель работает.

Это не то, что я понимаю в BlockingQueue, я предполагал, что пока производитель что-то производит и помещает в очередь, потребитель должен начать работу. Почему такое большое время ожидания на потребительском потоке выходит за рамки моего понимания.

Может кто-нибудь объяснить это немного больше? Есть ли простой способ профилировать такие приложения?

thread waiting

+0

Вы пытались использовать ExecutorService, который завершает очередь и пул потоков? Каковы преимущества вашей системы над использованием существующей библиотеки? –

+0

Это немного отличается от структуры ExecutorService. Каждый обработанный объект должен обрабатываться всеми потребительскими потоками. В ExecutorService только один работник будет работать на поданной работе. Я готов посмотреть, есть ли способ настроить ExecutorService для работы с этим дизайном, но я еще не нашел решение. – Wudong

+0

Это потому, что каждый поток выполняет другую работу на основе этого объекта? Вы просмотрели библиотеку Disruptor, поскольку она предназначена для более высокой производительности того, что вы пытаетесь сделать. т. е. разделить работу для каждого события по нескольким потокам. –

ответ

1

Это не то, что мое понимание BlockingQueue, я предположил, что до тех пор, как производитель продукции что-то и поставить в очередь, потребитель должен начать работу. Почему такое большое время ожидания на потребительском потоке выходит за рамки моего понимания.

Это, скорее всего, является не проблема с BlockingQueue.

  1. Возможно, вы ошибаетесь, и производитель отстает от потребителей. Может быть, продюсер разрывается и время от времени читает с загруженного диска и отстает.

  2. Возможно, потребители блокируют какой-то другой объект, а не BlockingQueue. Что потребители делают с данными? Записывают ли они его на диск или отправляют по сети? Любые другие операции, которые они могут заблокировать?

  3. Другая возможность заключается в том, что только одна цепочка не отстает от производителя и поэтому количество потоков ожидает в порядке потока LIFO. Другими словами, если поток только что закончил, возможно, он принимает последний элемент, добавленный производителем. Таким образом, несколько потоков остаются занятыми, а другие потоки остаются заблокированными. Я не уверен, что так реализована ваша очередь.

Есть ли простой способ профилировать это виды применения?

Одна вещь, чтобы сделать, это посмотреть на ваш стек следы, чтобы увидеть, где каждого из потоков блокируется.Это даст вам представление о том, действительно ли ваши потоки ждут в очереди блокировки. Вы можете использовать jconsole для просмотра живых потоков или отправки сигнала QUIT так часто.

Смежные вопросы