Тут не надо никакой многопоточности. Все такие симуляции выполняются в один поток с очередью событий.
Вот в 0 секунд у вас I1..I5 сгенерировали заявки, они пападают в накапители и сразу же из них в каналы. В 3 секунды K1 обработал заявку и свободен. Взял одну из накопителя. В 4 секунды K2 освободился, взял заявку из накопителя. В 5 секунд источники снова сгенерировали заявки... и т.д. Это можно просимулировать.
Реализуется это с помощью приоритетной очереди событий. В нее вы складываете новые события, а в основном цикле достаете оттуда событие с минимальным временем. На c++ это будет что-то вроде:
std::priority_queue<pair<int, Event>, std::vector, std::greater> queue
.
Еще вам надо написать классы для источника, накопителя, блокиратора с условиями (не понял, что это) и накопителя.
Например, источник в момент создания кладет в очередь событие "в 0 секунд я создам заявку". При выполнении этого события, во-первых, создается и кладется в очередь новое событие "в t+5 секунд я создам заявку". Во-вторых, надо посмотреть, куда заявки из этого источника попадают. Если это накопитель, то заявка пихается в него.
Класс накопителя при поступлении в него заявки, если он был пуст, смотрит, какие каналы к нему подключены (их может быть несколько) и, если какой-то из них свободен - сразу передает заявку туда. Если он был не пуст, то просто кладет заявку в очередь.
Класс канала при получении заявки создает событие во время t+время обработки заявки, что он освободится. При вы полнении этого события канал смотрит, к чему он подключен и если там не пустой накопитель, то забирает оттуда первую заявку.
Класс Event должен как-то запоминать какой объект это событие выполняет. А основной цикл должен этот код вызывать (и передавать туда время события).