Во-первых, поскольку ни в вашем OP, ни в дополнительном бите постановки задачи ничего не говорится о том, что система работает против настенных часов, не думайте, что это так. Все, что основано на снах в течение десяти секунд между созданием автомобилей, сводит вас с ума, пока вы тестируете это. Создайте простой интерфейс, чтобы обеспечить время для симуляции и работать против этого; если вам нужно привязать их к настенным часам, тогда вы можете, но вы также можете запускать тесты так же быстро, как ваша машина.
Во-вторых, обычно лучше проводить симуляции как события - машина прибывает на станцию, автомобили переходят из очереди в насос, машина покидает насос, прибывает танкер. Обычно работает приоритетная очередь событий, основанная на их времени; когда автомобиль начинает заправку, вы добавляете событие для его завершения в очередь событий с отметкой времени в будущем. Гораздо проще написать логику, чтобы не обрабатывать автомобили, если в данный момент есть танкер, чем возиться с приоритетами потоков.
Поскольку ваша задача требует, чтобы вы продемонстрировали некоторую синхронизацию между потоками, вы можете запустить процессы ожидания машин, заправки / выгрузки автоцистерн как отдельные потоки (в реальном программном обеспечении вы этого не сделаете, но, скорее всего, используете фьючерсы и executor, если вы хотели параллельное выполнение, но я предполагаю, что это педагогическая задача, и вам нужно показать какой-то дизайн потоков, а не позволить библиотеке разобраться во всем за вас).
Таким образом, для каждого временного среза вы обрабатываете события из очереди, ждете завершения обработки всех событий, а затем запрашиваете часы для следующего тика. Быстрые часы немедленно вернут метку времени в течение следующей секунды, или настенные часы будут ждать до следующей секунды системного времени.
Поскольку вам необходимо использовать потоки для каждой задачи, вам необходимо синхронизировать эти задачи в начале и в конце каждого временного интервала, а также необходимо синхронизировать или иным образом гарантировать, что поставленные в очередь события безопасно ставятся в очередь и видны раньше времени срез заканчивается.
Итак, задачи выглядят примерно так:
поступающие автомобили
- каждую секунду определяют количество прибывающих автомобилей. это будет распределение Пуассона.
- для каждого прибытия, опубликуйте событие, приехавшее на автомобиле (или опишите событие с количеством автомобилей)
(в качестве альтернативы используйте какой-то другой случайный механизм; большинство других подходов приведут к тому, что за один раз прибудет только одна машина, что не часто является полезным ограничением для размещения на модели)
входящие танкеры
- каждый (период прибытия танкера) после события прибытия танкера за насос
ожидающие машины
- увеличить число машин, ожидающих при прибытии машины
Насосы
- если танкер прибыл, установить флаг ожидания танкера
- если насос свободен, то
- если танкер ждет, сбросить флаг ожидания танкера, заполнить насос, событие после освобождения насоса для времени до заполнения насосов в будущем
- если в насосе есть топливо, и любой автомобиль ждет, уменьшите счетчик ожидания автомобилей, запостите событие без насоса для времени до заправки автомобиля в будущем
В заявлении о проблеме не ясно, должен ли танкер ждать, пока оба насоса освободятся, прежде чем он сможет начать их заполнять, и в этом случае вам нужно будет добавить еще одно состояние готовности танкера.
Если задачи находятся в разных потоках, вам нужно будет синхронизировать различные счетчики, либо «вручную», либо используя атомарные значения в java.util.concurrent.atomic.