Создайте генерик класс Склад (Storage
), у него есть методы положить товар и забрать товар (тип “товара” — аргумент генерика). У склада есть максимальная вместимость, которая задается при конструировании и не меняется. Если поток исполнения пытается положить товар на склад, а тот уже заполнен, поток засыпает, пока на складе не появится место. Если поток пытается взять товар со склада, а тот пуст, поток засыпает, пока на складе не появится товар.
Запросите числа N
, P
, C
. Создайте экземпляр склада строк размера N
. Создайте P
потоков-производителей (Producers), каждый из которых кладет на склад строку вида p<номер производителя>-<номер товара>
со всё возрастающим номером товара. Создайте C
потоков-потребителей (Consumers), каждый из которых раз в секунду берет со склада строку и печатает на консоль c<номер потребителя> consumes <товар>
, после чего ждет 50-100мс. Вывод будет выглядеть примерно так:
c0 consumes p9-1
c2 consumes p1-3
c3 consumes p2-2
c1 consumes p5-4
c3 consumes p9-5
c1 consumes p7-6
Обратите внимание, что если функция main() закончила свою работу, программа не завершается, пока не закончат выполнение все потоки. Вызов System.exit() завершает программу, даже если есть активные потоки.
- Перед стартом потоков запросите число
T
. По прошествииT
секунд после старта приложения начните процедуру завершения. Сначала завершите всех производителей (Producers). Напечатайте “производители завершены”. Затем дождитесь полного опустошения склада. Напечатайте “склад пуст”. Затем закройте всех потребителей (Consumers). Напечатайте “потребители завершены”. После этого завершите программу. - Пусть каждый производитель и потребитель ведет учет, сколько товаров он произвел/потребил. Склад ведет учет, сколько товаров через него прошло. При завершении программы выводите эту информацию для каждого потребителя, производителя и склада.