Я новичок в clojure и пытаюсь понять, как правильно использовать его функции concurrency, поэтому любые критические замечания и предложения оценены. Поэтому я пытаюсь написать небольшую тестовую программу в clojure, которая работает следующим образом:
- там 5 производителей и 2 потребителя
- продюсер ждет случайного времени, а затем выталкивает номер в общую очередь.
- потребитель должен вывести номер из очереди, как только очередь будет непустой, а затем засыпать на короткое время, чтобы имитировать выполнение работы.
- потребители должны блокировать, когда очередь пуста.
- производители должны блокировать, когда очередь имеет более 4 элементов в ней, чтобы предотвратить ее рост.
Вот мой план для каждого шага выше:
- производители и потребители будут агентами, которые не заботятся о своем состоянии (только нулевые ценности или что-то еще); я просто использую агентов для отправки функции "потребитель" или "производитель", чтобы сделать это в какое-то время. Тогда общая очередь будет (def queue (ref [])). Может быть, это должен быть атом?
в функции агента производителя, просто (Thread/sleep (rand-int 1000)), а затем (dosync (alter queue conj (rand-int 100))), чтобы нажать на очередь. Я думаю, чтобы потребительские агенты наблюдали за очередью изменений с помощью add-watcher. Не уверен в этом, хотя... он будет пробуждать потребителей при любых изменениях, даже если изменение исходит от потребителя, который тянет что-то (возможно, делает его пустым). Возможно, проверка этого в функции наблюдателя достаточно. Другая проблема, которую я вижу, заключается в том, что, если все потребители заняты, что происходит, когда производитель добавляет что-то новое в очередь? Наблюдает ли наблюдаемое событие очередь на каком-то потребительском агенте или исчезает? см. выше Я действительно не знаю, как это сделать. Я слышал, что clojure seque может быть полезным, но я не мог найти достаточно документа о том, как его использовать, и мое первоначальное тестирование, похоже, не работает (извините, у меня больше нет кода).