Возникла проблема с пониманием блокировки / условий и проблемы с кодом - PullRequest
0 голосов
/ 12 июня 2019

В настоящее время я пытаюсь разобраться в работе с многопоточностью и написать программу «Порт / Гавань», которая также содержит систему Ships and Delivering.Корабли загружают и доставляют контейнеры в порт, и если порт заполнен или пуст. Доставляющая система будет загружаться оттуда или доставлять новые контейнеры. Проблема в том, что я просто хочу контролировать доставку системы, используя await / signal, может кто-то помочь и посоветовать мне.Спасибо)

public class DeliveryController {

    private static final Logger LOGGER = LogManager.getLogger(DeliveryController.class);
    private Port port;
    private Condition isFull;

    public DeliveryController(Port port){
        this.port = port;
        isFull = port.getLock().newCondition();
    }

    public void deliverToPort(Port port, Ship ship) {
        port.getLock().lock();
        try {
            LOGGER.info(ship.getModel() + " delivering containers to port");
            while (ship.getContainerCount() != 0) {
                port.loadContainers(ship.getContainerCount());
                ship.deliverContainers(ship.getContainerCount());
                while (port.getContainerCount() >= Port.CAPACITY / 2 + 500)
                    try {
                        LOGGER.info("Port is full,waiting for a container service " + ship.getModel());
                        isFull.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LOGGER.info("Finished delivering to port " + ship.getModel());
        } finally {
            port.getLock().unlock();
        }
    }


    public void loadFromPort(Port port, int containerAmount) {
        port.getLock().lock();
        try {
            LOGGER.info("Getting containers from port");
            while (port.getContainerCount() >= Delivery.MIN_CONTAINER_AMOUNT) {
                port.unloadContainers(containerAmount);
            }
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LOGGER.info("Port is free,continue delivering");
            isFull.signal();
        } finally {
            port.getLock().unlock();
        }
    }
}
public class LoadController {

    private static final Logger LOGGER = LogManager.getLogger(LoadController.class);
    private Port port;
    private Condition isEmpty;

    public LoadController(Port port) {
        this.port = port;
        isEmpty = port.getLock().newCondition();
    }

    public void loadFromPort(Port port, Ship ship, int containerCount) {
        port.getLock().lock();
        try {
            while (ship.getContainerCount() <= ship.getCapacity()) {
                port.unloadContainers(containerCount);
                ship.loadContainers(containerCount);
                while (port.getContainerCount() < Delivery.MIN_CONTAINER_AMOUNT) {
                    try {
                        LOGGER.info("Port is free,waiting for a container delivering " + ship.getModel());
                        isEmpty.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            LOGGER.info("Finished loading to ship " + ship.getModel());
        } finally {
            port.getLock().unlock();
        }
    }


    public void deliverToPort(Port port, int containerAmount) {
        port.getLock().lock();
        try {
            LOGGER.info("Started Delivering containers to port");
            while (port.getContainerCount() < Port.CAPACITY) {
                port.loadContainers(containerAmount);
            }
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LOGGER.info("Delivering to port finished");
            isEmpty.signal();
        } finally {
            port.getLock().unlock();
        }
    }
}
public class Ship implements Runnable {

    private static final Logger LOGGER = LogManager.getLogger(Ship.class);
    private int capacity;
    private String model;
    private ServiceType serviceType;
    private AtomicInteger containerCount = new AtomicInteger();
    private Port port;
    public Thread load, deliver;
    public boolean running = false;
    private Semaphore semaphore;
    private LoadController loadController;
    private static final int LOAD_CONTAINER_AMOUNT = 50;
    private DeliveryController deliveryController;

    public Ship(int containerCount, String model, ServiceType serviceType, int capacity, Port port,
                LoadController loadController, DeliveryController deliveryController, Semaphore semaphore) {
        this.capacity = capacity;
        this.model = model;
        this.serviceType = serviceType;
        this.containerCount.set(containerCount);
        this.port = port;
        this.loadController = loadController;
        this.deliveryController = deliveryController;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            LOGGER.info("Ship " + model + " came to the port");
            if (serviceType.toString().equals("LOAD")) {
                LOGGER.info("Ship " + model + " is loading");
                load();
            } else if (serviceType.toString().equals("DELIVERY")) {
                LOGGER.info("Ship " + model + " is delivering");
                deliver();
            } else {
                LOGGER.info("Ship " + model + " is delivering and loading");
                deliver();
                load();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info(model + " finished and leaving the port");
        semaphore.release();
    }

    private void load() {
        load = new Thread(() -> {
            loadController.loadFromPort(port, this, LOAD_CONTAINER_AMOUNT);
        });
        load.start();
    }

    private void deliver() {
        deliver = new Thread(() -> {
            deliveryController.deliverToPort(port, this);
        });
        deliver.start();

    }
public class Delivery implements Runnable {

    private Port port;
    public final static int MIN_CONTAINER_AMOUNT = 250;
    private final static int DELIVER_CONTAINER_COUNT = 200;
    private LoadController loadController;
    private DeliveryController deliveryController;
    private Thread loadContainers, deliverContainers;

    public Delivery(Port port, LoadController loadController, DeliveryController deliveryController) {
        this.port = port;
        this.loadController = loadController;
        this.deliveryController = deliveryController;
    }

    @Override
    public void run() {

    }

    private void loadContainers() {
        loadContainers = new Thread(new Runnable() {
            @Override
            public void run() {
                deliveryController.loadFromPort(port, DELIVER_CONTAINER_COUNT);
            }
        });
        loadContainers.start();
    }

    private void deliverContainers() {
        deliverContainers = new Thread(() -> loadController.deliverToPort(port, DELIVER_CONTAINER_COUNT));
        deliverContainers.start();
    }

}

в Корабле все в порядке, я хочу, чтобы при загрузке / доставке контейнеров и доставке поток работал бесконечно, доставка / загрузка в портовые методыкогда это необходимо, используя await ().

...