Многопоточность Java для нескольких производителей и потребителей не работает по назначению - PullRequest
0 голосов
/ 24 сентября 2019

Я работаю над несколькими вариантами использования для производителя и потребителя проблемы «производитель-потребитель» с Java.Код на github .Та же самая реализация работала для случая использования одного производителя , но велась странно для случая использования нескольких производителей.

У меня есть несколько вопросов относительно вывода:

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

Producer t1 has lock
t5 produced 1, integerQueue: [1]
Producer t5 notifiedAll
  1. Я думал, что все потоки должны конкурировать за блокировку, и должен быть не более одного потока, который имеет блокировку всех времен?Все производители делят замок?Как потребительский поток t5 получил блокировку, когда производственный поток t1 удерживал ее?

После того, как он некоторое время работает, появляется еще одно странное явление:

Producer t5 has lock
t5 produced 10, integerQueue: [8, 9, 10]
Producer t5 notifiedAll

Producer t5 has lock
t5 produced 11, integerQueue: [8, 9, 10, 11]
Producer t5 notifiedAll

Consumer t8 has lock
t8 consumed 8, integerQueue: [9, 10, 11]
Consumer t8 notified All

Consumer t8 has lock
t8 consumed 9, integerQueue: [10, 11]
Consumer t8 notified All
Кажется, что все потоки, кроме одного производителя и потребителя, умерли, и эти два переключают блокировку между собой.Почему это происходит?Что случилось со всеми другими производителями и потребителями?

Любая помощь очень ценится.

1 Ответ

1 голос
/ 24 сентября 2019

Вы используете один экземпляр вашего Producer5 работоспособного и много раз отправляете его в службу исполнения.

    Producer5 producer = new Producer5(queue, maxCapacity);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);

Таким образом, ваше поле threadName в этом единственном экземпляре Producer5 будет перезаписано несколько раз и бесполезно (оно больше не будет выводить имя потока, который фактически выполняется, более того, онодолжно быть volatile для правильного обновления несколькими потоками - для некоторого определения правильно).

  System.out.println(String.format("\nProducer %s has lock",
    threadName // this will be the name of the last thread that entered `run`, 
              // they all share the same instance 
  )); 

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


Как потребительский поток t5 получил блокировку, когда поток производителя t1 удерживал ее?

Это был все еще поток t1, выполняющий этот код, но threadName поле тем временем обновляется темой t5.Сильно вводящий в заблуждение вывод.

Кажется, что все потоки, кроме одного производителя и потребителя, умерли, и эти два переключают блокировку между собой.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...