/
fedion
/
hw1
Обзор
Документация
Войти
/
fedion
/
hw1
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
answer
src/main/java/org/example/Warehouse.java
156 строк
5 KB
Ioann
реализация hw1
12 окт 2025, 17:24
12 окт 2025, 17:24
955a6a5
Код
Авторство
О чём код?
package org.example; import lombok.Getter; import lombok.extern.log4j.Log4j2; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @Log4j2 @Getter public class Warehouse extends Thread { private final List<Block> storage = new ArrayList<>(); private final Lock lock = new ReentrantLock(); private final Condition isPresenceTruck = lock.newCondition(); private Truck currentTruck; public Warehouse(String name) { super(name); } public Warehouse(String name, Collection<Block> initialStorage) { this(name); storage.addAll(initialStorage); } @Override public void run() { Truck truck; while (!currentThread().isInterrupted()) { truck = getNextArrivedTruck(); if (truck == null) { try { sleep(100); } catch (InterruptedException e) { if (currentThread().isInterrupted()) { break; } } continue; } if (truck.getBlocks().isEmpty()) { loadTruck(truck); } else { unloadTruck(truck); } truck.setReady(true); //Не знаю, как без этого завершения в виде проставления флага проверять окончание работы //т.к. логика для каждой фабрики отличается, а они обе засунуты в одну } log.info("Warehouse thread interrupted"); } private void loadTruck(Truck truck) { log.info("Loading truck {}", truck.getName()); Collection<Block> blocksToLoad = getFreeBlocks(truck.getCapacity()); try { sleep(10L * blocksToLoad.size()); } catch (InterruptedException e) { log.error("Interrupted while loading truck", e); } truck.getBlocks().addAll(blocksToLoad); log.info("Truck loaded {}", truck.getName()); } private Collection<Block> getFreeBlocks(int maxItems) { //TODO необходимо реализовать потокобезопасную логику по получению свободных блоков //TODO 1 блок грузится в 1 грузовик, нельзя клонировать блоки во время загрузки var blocksToTravel = maxItems > this.storage.size() ? new ArrayList<>(this.storage) : new ArrayList<>(this.storage.subList(0, maxItems)); this.storage.removeAll(blocksToTravel); return blocksToTravel; } private void returnBlocksToStorage(List<Block> returnedBlocks) { //TODO реализовать потокобезопасную логику по возврату блоков на склад storage.addAll(returnedBlocks); } private void unloadTruck(Truck truck) { log.info("Unloading truck {}", truck.getName()); List<Block> arrivedBlocks = truck.getBlocks(); try { sleep(100L * arrivedBlocks.size()); } catch (InterruptedException e) { log.error("Interrupted while unloading truck", e); } returnBlocksToStorage(arrivedBlocks); truck.getBlocks().clear(); log.info("Truck unloaded {}", truck.getName()); } private Truck getNextArrivedTruck() { //TODO необходимо реализовать логику по получению следующего прибывшего грузовика внутри потока склада lock.lock(); try { checkTruckPresenceInWarehouse(); if (currentTruck.isReady()) { currentTruck.lock(); try { currentTruck.signalAll(); } finally { currentTruck.unlock(); } currentTruck = null; isPresenceTruck.signalAll(); } } finally { lock.unlock(); } return currentTruck; } private void checkTruckPresenceInWarehouse() { while (currentTruck == null) { try { isPresenceTruck.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public void arrive(Truck truck) { //TODO необходимо реализовать логику по сообщению потоку склада о том, что грузовик приехал //TODO так же дождаться разгрузки блоков, при возврате из этого метода - грузовик покинет склад lock.lock(); try { while (currentTruck != null) { isPresenceTruck.await(); } currentTruck = truck; isPresenceTruck.signalAll(); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } truck.lock(); while (!truck.isReady()) { truck.await(); } truck.setReady(false); } }