From 6bdb5f3744c8a91e53e2c1f42b3b1e02bb587900 Mon Sep 17 00:00:00 2001 From: Nrydo Date: Wed, 27 Dec 2023 07:50:24 +0300 Subject: [PATCH 1/2] lab2 without logging --- .../nrydo/docks_and_hobos/ConfigReader.java | 114 ++++++++++++++++++ lab-02/by/nrydo/docks_and_hobos/Dock.java | 84 +++++++++++++ lab-02/by/nrydo/docks_and_hobos/Hobo.java | 87 +++++++++++++ .../by/nrydo/docks_and_hobos/HoboGroup.java | 85 +++++++++++++ lab-02/by/nrydo/docks_and_hobos/Main.java | 34 ++++++ lab-02/by/nrydo/docks_and_hobos/Ship.java | 29 +++++ .../nrydo/docks_and_hobos/ShipGenerator.java | 34 ++++++ lab-02/by/nrydo/docks_and_hobos/Tunnel.java | 35 ++++++ lab-02/by/nrydo/docks_and_hobos/config.json | 13 ++ lab-02/lib/json-simple-1.1.1.jar | Bin 0 -> 23737 bytes 10 files changed, 515 insertions(+) create mode 100644 lab-02/by/nrydo/docks_and_hobos/ConfigReader.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/Dock.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/Hobo.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/HoboGroup.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/Main.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/Ship.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/Tunnel.java create mode 100644 lab-02/by/nrydo/docks_and_hobos/config.json create mode 100644 lab-02/lib/json-simple-1.1.1.jar diff --git a/lab-02/by/nrydo/docks_and_hobos/ConfigReader.java b/lab-02/by/nrydo/docks_and_hobos/ConfigReader.java new file mode 100644 index 0000000..eb62d8d --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/ConfigReader.java @@ -0,0 +1,114 @@ +package by.nrydo.docks_and_hobos; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.FileReader; +import java.util.Arrays; + +public class ConfigReader { + private static ConfigReader instance = null; + + private int generatingTime; + private int shipCapacityMin; + private int shipCapacityMax; + private String[] cargoTypes; + private int maxShips; + private int unloadingSpeed; + private int dockCapacity; + private int hobos; + private int[] ingredientsCount; + private int stealingTime; + private int eatingTime; + + private ConfigReader() { + } + + public static ConfigReader getInstance() { + if (instance == null) { + instance = new ConfigReader(); + } + return instance; + } + + public void readConfig(String filePath) { + JSONParser parser = new JSONParser(); + + try (FileReader reader = new FileReader(filePath)) { + Object obj = parser.parse(reader); + JSONObject jsonObject = (JSONObject) obj; + + generatingTime = Math.toIntExact((Long) jsonObject.get("generating_time")); + shipCapacityMin = Math.toIntExact((Long) jsonObject.get("ship_capacity_min")); + shipCapacityMax = Math.toIntExact((Long) jsonObject.get("ship_capacity_max")); + + JSONArray cargoTypesJson = (JSONArray) jsonObject.get("cargo_types"); + cargoTypes = new String[cargoTypesJson.size()]; + for (int i = 0; i < cargoTypesJson.size(); i++) { + cargoTypes[i] = (String) cargoTypesJson.get(i); + } + + maxShips = Math.toIntExact((Long) jsonObject.get("max_ships")); + unloadingSpeed = Math.toIntExact((Long) jsonObject.get("unloading_speed")); + dockCapacity = Math.toIntExact((Long) jsonObject.get("dock_capacity")); + hobos = Math.toIntExact((Long) jsonObject.get("hobos")); + + JSONArray ingredientsCountJson = (JSONArray) jsonObject.get("ingredients_count"); + ingredientsCount = new int[cargoTypesJson.size()]; + for (int i = 0; i < ingredientsCountJson.size(); i++) { + ingredientsCount[i] = ((Long) ingredientsCountJson.get(i)).intValue(); + } + + stealingTime = Math.toIntExact((Long) jsonObject.get("stealing_time")); + eatingTime = Math.toIntExact((Long) jsonObject.get("eating_time")); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public int getGeneratingTime() { + return generatingTime; + } + + public int getShipCapacityMin() { + return shipCapacityMin; + } + + public int getShipCapacityMax() { + return shipCapacityMax; + } + + public String[] getCargoTypes() { + return cargoTypes; + } + + public int getMaxShips() { + return maxShips; + } + + public int getUnloadingSpeed() { + return unloadingSpeed; + } + + public int getDockCapacity() { + return dockCapacity; + } + + public int getHobos() { + return hobos; + } + + public int[] getIngredientsCount() { + return ingredientsCount; + } + + public int getStealingTime() { + return stealingTime; + } + + public int getEatingTime() { + return eatingTime; + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/Dock.java b/lab-02/by/nrydo/docks_and_hobos/Dock.java new file mode 100644 index 0000000..0790ff0 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/Dock.java @@ -0,0 +1,84 @@ +package by.nrydo.docks_and_hobos; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class Dock implements Runnable { + private final int unloadingSpeed; + private final int dockCapacity; + private final int[] currentCargoStore; + private final Tunnel tunnel; + private final int maxBatchCount = 1; + private final Semaphore cargoSemaphore; + private final Lock stealingLock; + private int unloadThisSecond; + private int unloadBatchCount; + + public Dock(Tunnel tunnel) { + this.tunnel = tunnel; + unloadingSpeed = ConfigReader.getInstance().getUnloadingSpeed(); + dockCapacity = ConfigReader.getInstance().getDockCapacity(); + currentCargoStore = new int[ConfigReader.getInstance().getCargoTypes().length]; + cargoSemaphore = new Semaphore(0); + stealingLock = new ReentrantLock(); + unloadThisSecond = 0; + unloadBatchCount = 0; + } + + @Override + public void run() { + while (true) { + Ship ship = tunnel.getShip(); + unloadCargo(ship); + } + } + + public int steal() { + try { + cargoSemaphore.acquire(); + stealingLock.lock(); + List cargos = new ArrayList<>(); + for (int i = 0; i < currentCargoStore.length; i++) { + if (currentCargoStore[i] > 0) { + cargos.add(i); + } + } + int cargo = cargos.get((new Random()).nextInt(cargos.size())); + currentCargoStore[cargo]--; + stealingLock.unlock(); + return cargo; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + private void unloadCargo(Ship ship) { + while (ship.getStore() > 0) { + try { + int cargo = currentCargoStore[ship.getCargoType()]; + int batchSize = ship.take(getBatchSize()); + int cargoToUnload = Math.min(batchSize, dockCapacity - cargo); + cargoSemaphore.release(batchSize); + currentCargoStore[ship.getCargoType()] = cargo + cargoToUnload; + Thread.sleep(999L / maxBatchCount + 1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + private int getBatchSize() { + if (unloadBatchCount == 0) { + unloadBatchCount = maxBatchCount; + unloadThisSecond = unloadingSpeed; + } + int result = (unloadThisSecond + unloadBatchCount / 2) / unloadBatchCount; + unloadThisSecond -= result; + unloadBatchCount--; + return result; + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/Hobo.java b/lab-02/by/nrydo/docks_and_hobos/Hobo.java new file mode 100644 index 0000000..16005e9 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/Hobo.java @@ -0,0 +1,87 @@ +package by.nrydo.docks_and_hobos; + +import java.util.Arrays; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.Lock; + +public class Hobo implements Runnable { + private boolean isCook = false; + private Semaphore cookSemaphore; + private Semaphore eatingSemaphore; + private Lock ingredientsLock; + private final CyclicBarrier eatingBarrier; + private final Dock dock; + private final HoboGroup group; + + public Hobo(HoboGroup group, Dock dock, CyclicBarrier eatingBarrier) { + this.dock = dock; + this.group = group; + this.eatingBarrier = eatingBarrier; + } + + public void becomeCook(Semaphore cookSemaphore, Lock ingredientsLock, Semaphore eatingSemaphore) { + isCook = true; + this.cookSemaphore = cookSemaphore; + this.ingredientsLock = ingredientsLock; + this.eatingSemaphore = eatingSemaphore; + } + + @Override + public void run() { + int stealingTime = ConfigReader.getInstance().getStealingTime(); + try { + if (isCook) { + while (true) { + tryCook(); + } + } + while (true) { + Thread.sleep(stealingTime * 1000L); + while (group.isEating().get()) { + eatingBarrier.await(); + Thread.sleep(ConfigReader.getInstance().getEatingTime() * 1000L); + } + stealIngredient(); + } + } catch (InterruptedException | BrokenBarrierException e) { + e.printStackTrace(); + } + } + + private void stealIngredient() { + int ingredient = dock.steal(); + System.out.println("Putting " + this.hashCode()); + group.putIngredient(ingredient); + System.out.println("Stealing " + this.hashCode() + "\n" + Arrays.toString(group.getIngredients())); + } + + private void tryCook() { + try { + cookSemaphore.acquire(); + ingredientsLock.lock(); + if (group.isEating().get()) { + ingredientsLock.unlock(); + eatingBarrier.await(); + Thread.sleep(ConfigReader.getInstance().getEatingTime() * 1000L); + return; + } + int[] ingredients = group.getIngredients(); + int[] ingredientsCount = ConfigReader.getInstance().getIngredientsCount(); + for (int i = 0; i < ingredients.length; i++) { + if (ingredients[i] < ingredientsCount[i]) { + ingredientsLock.unlock(); + return; + } + } + eatingSemaphore.release(); + group.isEating().set(true); + ingredientsLock.unlock(); + eatingBarrier.await(); + Thread.sleep(ConfigReader.getInstance().getEatingTime() * 1000L); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java b/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java new file mode 100644 index 0000000..25f99ff --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java @@ -0,0 +1,85 @@ +package by.nrydo.docks_and_hobos; + +import java.util.Random; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class HoboGroup implements Runnable { + private final Thread[] threads; + private final int[] ingredients; + private final Semaphore cookSemaphore; + private final Semaphore eatingSemaphore; + private final Lock ingredientsLock; + private final CyclicBarrier eatingBarrier; + private final AtomicBoolean eating; + + HoboGroup(Dock dock) { + Hobo[] hobos = new Hobo[ConfigReader.getInstance().getHobos()]; + ingredients = new int[ConfigReader.getInstance().getIngredientsCount().length]; + + cookSemaphore = new Semaphore(0); + eatingSemaphore = new Semaphore(0); + ingredientsLock = new ReentrantLock(); + eatingBarrier = new CyclicBarrier(hobos.length + 1, this::eat); + eating = new AtomicBoolean(false); + + threads = new Thread[hobos.length]; + + for (int i = 0; i < hobos.length; i++) { + hobos[i] = new Hobo(this, dock, eatingBarrier); + threads[i] = new Thread(hobos[i]); + } + + Random random = new Random(); + + int firstCook = random.nextInt(hobos.length); + int secondCook = (firstCook + random.nextInt(hobos.length - 1) + 1) % hobos.length; + + hobos[firstCook].becomeCook(cookSemaphore, ingredientsLock, eatingSemaphore); + hobos[secondCook].becomeCook(cookSemaphore, ingredientsLock, eatingSemaphore); + } + + void eat() { + int[] ingredientsCount = ConfigReader.getInstance().getIngredientsCount(); + for (int i = 0; i < ingredients.length; i++) { + ingredients[i] -= ingredientsCount[i]; + } + eating.set(false); + } + + public void putIngredient(int ingredient) { + ingredientsLock.lock(); + ingredients[ingredient]++; + cookSemaphore.release(); + ingredientsLock.unlock(); + } + + public int[] getIngredients() { + return ingredients; + } + + public AtomicBoolean isEating() { + return eating; + } + + @Override + public void run() { + for (Thread thread : threads) { + thread.start(); + } + + try { + while (true) { + eatingSemaphore.acquire(); + cookSemaphore.release(); + eatingBarrier.await(); + } + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/Main.java b/lab-02/by/nrydo/docks_and_hobos/Main.java new file mode 100644 index 0000000..bcacc20 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/Main.java @@ -0,0 +1,34 @@ +package by.nrydo.docks_and_hobos; + +public class Main { + public static void main(String[] args) { + if (args.length < 1) { + throw new IllegalArgumentException(); + } + + String configFilePath = args[0]; + + ConfigReader config = ConfigReader.getInstance(); + config.readConfig(configFilePath); + + Tunnel tunnel = new Tunnel(); + ShipGenerator shipGenerator = new ShipGenerator(tunnel); + Dock dock = new Dock(tunnel); + HoboGroup hobos = new HoboGroup(dock); + + Thread shipGeneratorThread = new Thread(shipGenerator); + Thread dockThread = new Thread(dock); + Thread hobosThread = new Thread(hobos); + + shipGeneratorThread.start(); + dockThread.start(); + hobosThread.start(); + + try { + shipGeneratorThread.join(); + dockThread.join(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/lab-02/by/nrydo/docks_and_hobos/Ship.java b/lab-02/by/nrydo/docks_and_hobos/Ship.java new file mode 100644 index 0000000..e8d1133 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/Ship.java @@ -0,0 +1,29 @@ +package by.nrydo.docks_and_hobos; + +public class Ship { + private int store; + private final int cargoType; + + public Ship(int capacity, int cargoType) { + this.store = capacity; + this.cargoType = cargoType; + } + + public int getStore() { + return store; + } + + public int getCargoType() { + return cargoType; + } + + public int take(int x) { + if (store > x) { + store -= x; + return x; + } + int result = store; + store = 0; + return result; + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java b/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java new file mode 100644 index 0000000..0bdd4e7 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java @@ -0,0 +1,34 @@ +package by.nrydo.docks_and_hobos; + +import java.util.Random; + +public class ShipGenerator implements Runnable { + private final Tunnel tunnel; + + public ShipGenerator(Tunnel tunnel) { + this.tunnel = tunnel; + } + + @Override + public void run() { + ConfigReader config = ConfigReader.getInstance(); + while (true) { + try { + tunnel.addShip(generateShip()); + Thread.sleep(config.getGeneratingTime() * 1000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private Ship generateShip() { + Random random = new Random(); + ConfigReader config = ConfigReader.getInstance(); + int minCapacity = config.getShipCapacityMin(); + int maxCapacity = config.getShipCapacityMax(); + int capacity = random.nextInt(maxCapacity - minCapacity + 1) + minCapacity; + int cargoType = random.nextInt(config.getCargoTypes().length); + return new Ship(capacity, cargoType); + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/Tunnel.java b/lab-02/by/nrydo/docks_and_hobos/Tunnel.java new file mode 100644 index 0000000..c5ad4d8 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/Tunnel.java @@ -0,0 +1,35 @@ +package by.nrydo.docks_and_hobos; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Semaphore; + +public class Tunnel { + private final Semaphore placeSemaphore; + private final Semaphore shipSemaphore; + private final Queue ships; + + public Tunnel() { + placeSemaphore = new Semaphore(ConfigReader.getInstance().getMaxShips()); + shipSemaphore = new Semaphore(0); + ships = new ConcurrentLinkedQueue<>(); + } + + public void addShip(Ship ship) { + if (placeSemaphore.tryAcquire()) { + ships.add(ship); + shipSemaphore.release(); + } + } + + public Ship getShip() { + try { + shipSemaphore.acquire(); + Ship ship = ships.poll(); + placeSemaphore.release(); + return ship; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/lab-02/by/nrydo/docks_and_hobos/config.json b/lab-02/by/nrydo/docks_and_hobos/config.json new file mode 100644 index 0000000..5ca0197 --- /dev/null +++ b/lab-02/by/nrydo/docks_and_hobos/config.json @@ -0,0 +1,13 @@ +{ + "generating_time": 5, + "ship_capacity_min": 1, + "ship_capacity_max": 5, + "cargo_types": ["Bread", "Cheese", "Meat"], + "max_ships": 3, + "unloading_speed": 5, + "dock_capacity": 100, + "hobos": 5, + "ingredients_count": [1, 1, 1], + "stealing_time": 3, + "eating_time": 5 +} \ No newline at end of file diff --git a/lab-02/lib/json-simple-1.1.1.jar b/lab-02/lib/json-simple-1.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..66347a6c86b7d6442358ca7643e4dc484fb01866 GIT binary patch literal 23737 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 A{Qv*} literal 0 HcmV?d00001 From a63849d454f91002221a0b630258c62c7c13313f Mon Sep 17 00:00:00 2001 From: Nrydo Date: Wed, 27 Dec 2023 08:09:43 +0300 Subject: [PATCH 2/2] lab2 logging --- lab-02/by/nrydo/docks_and_hobos/Dock.java | 25 +++++++++++++- lab-02/by/nrydo/docks_and_hobos/Hobo.java | 24 +++++++++++-- .../by/nrydo/docks_and_hobos/HoboGroup.java | 27 +++++++++++++-- lab-02/by/nrydo/docks_and_hobos/Ship.java | 4 +++ .../nrydo/docks_and_hobos/ShipGenerator.java | 31 +++++++++++++++-- lab-02/by/nrydo/docks_and_hobos/Tunnel.java | 34 +++++++++++++++++-- lab-02/log/dock.log | 10 ++++++ lab-02/log/hobo.log | 26 ++++++++++++++ lab-02/log/hobo.log.1 | 26 ++++++++++++++ lab-02/log/hobo.log.2 | 26 ++++++++++++++ lab-02/log/hobo_group.log | 2 ++ lab-02/log/ship_generator.log | 10 ++++++ lab-02/log/tunnel.log | 20 +++++++++++ 13 files changed, 254 insertions(+), 11 deletions(-) create mode 100644 lab-02/log/dock.log create mode 100644 lab-02/log/hobo.log create mode 100644 lab-02/log/hobo.log.1 create mode 100644 lab-02/log/hobo.log.2 create mode 100644 lab-02/log/hobo_group.log create mode 100644 lab-02/log/ship_generator.log create mode 100644 lab-02/log/tunnel.log diff --git a/lab-02/by/nrydo/docks_and_hobos/Dock.java b/lab-02/by/nrydo/docks_and_hobos/Dock.java index 0790ff0..a1d32c0 100644 --- a/lab-02/by/nrydo/docks_and_hobos/Dock.java +++ b/lab-02/by/nrydo/docks_and_hobos/Dock.java @@ -6,6 +6,10 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; public class Dock implements Runnable { private final int unloadingSpeed; @@ -17,6 +21,7 @@ public class Dock implements Runnable { private final Lock stealingLock; private int unloadThisSecond; private int unloadBatchCount; + private final Logger logger; public Dock(Tunnel tunnel) { this.tunnel = tunnel; @@ -27,6 +32,19 @@ public Dock(Tunnel tunnel) { stealingLock = new ReentrantLock(); unloadThisSecond = 0; unloadBatchCount = 0; + logger = createLogger(); + } + + private Logger createLogger() { + Logger logger = Logger.getLogger(Dock.class.getName()); + try { + FileHandler fileHandler = new FileHandler("log/dock.log"); + fileHandler.setFormatter(new SimpleFormatter()); + logger.addHandler(fileHandler); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to create logger", e); + } + return logger; } @Override @@ -64,6 +82,7 @@ private void unloadCargo(Ship ship) { int cargoToUnload = Math.min(batchSize, dockCapacity - cargo); cargoSemaphore.release(batchSize); currentCargoStore[ship.getCargoType()] = cargo + cargoToUnload; + logCargoUnloading(cargoToUnload, ConfigReader.getInstance().getCargoTypes()[ship.getCargoType()]); Thread.sleep(999L / maxBatchCount + 1); } catch (InterruptedException e) { throw new RuntimeException(e); @@ -81,4 +100,8 @@ private int getBatchSize() { unloadBatchCount--; return result; } -} + + private void logCargoUnloading(int cargoToUnload, String cargoType) { + logger.info(String.format("Unloaded cargo: quantity=%d, type=%s", cargoToUnload, cargoType)); + } +} \ No newline at end of file diff --git a/lab-02/by/nrydo/docks_and_hobos/Hobo.java b/lab-02/by/nrydo/docks_and_hobos/Hobo.java index 16005e9..ef6d6a3 100644 --- a/lab-02/by/nrydo/docks_and_hobos/Hobo.java +++ b/lab-02/by/nrydo/docks_and_hobos/Hobo.java @@ -5,6 +5,10 @@ import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; public class Hobo implements Runnable { private boolean isCook = false; @@ -14,11 +18,26 @@ public class Hobo implements Runnable { private final CyclicBarrier eatingBarrier; private final Dock dock; private final HoboGroup group; + private final Logger logger; public Hobo(HoboGroup group, Dock dock, CyclicBarrier eatingBarrier) { this.dock = dock; this.group = group; this.eatingBarrier = eatingBarrier; + this.logger = createLogger(); + } + + private Logger createLogger() { + Logger logger = Logger.getLogger(Hobo.class.getName()); + try { + // Создание обработчика файла логов + FileHandler fileHandler = new FileHandler("log/hobo.log"); + fileHandler.setFormatter(new SimpleFormatter()); + logger.addHandler(fileHandler); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to create logger", e); + } + return logger; } public void becomeCook(Semaphore cookSemaphore, Lock ingredientsLock, Semaphore eatingSemaphore) { @@ -46,15 +65,14 @@ public void run() { stealIngredient(); } } catch (InterruptedException | BrokenBarrierException e) { - e.printStackTrace(); + logger.log(Level.SEVERE, "Thread interrupted", e); } } private void stealIngredient() { int ingredient = dock.steal(); - System.out.println("Putting " + this.hashCode()); group.putIngredient(ingredient); - System.out.println("Stealing " + this.hashCode() + "\n" + Arrays.toString(group.getIngredients())); + logger.info("Stole ingredient: " + ConfigReader.getInstance().getCargoTypes()[ingredient]); } private void tryCook() { diff --git a/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java b/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java index 25f99ff..5b89b74 100644 --- a/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java +++ b/lab-02/by/nrydo/docks_and_hobos/HoboGroup.java @@ -7,6 +7,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; public class HoboGroup implements Runnable { private final Thread[] threads; @@ -16,6 +20,7 @@ public class HoboGroup implements Runnable { private final Lock ingredientsLock; private final CyclicBarrier eatingBarrier; private final AtomicBoolean eating; + private final Logger logger; HoboGroup(Dock dock) { Hobo[] hobos = new Hobo[ConfigReader.getInstance().getHobos()]; @@ -28,6 +33,7 @@ public class HoboGroup implements Runnable { eating = new AtomicBoolean(false); threads = new Thread[hobos.length]; + logger = createLogger(); for (int i = 0; i < hobos.length; i++) { hobos[i] = new Hobo(this, dock, eatingBarrier); @@ -43,7 +49,24 @@ public class HoboGroup implements Runnable { hobos[secondCook].becomeCook(cookSemaphore, ingredientsLock, eatingSemaphore); } + private Logger createLogger() { + Logger logger = Logger.getLogger(HoboGroup.class.getName()); + try { + FileHandler fileHandler = new FileHandler("log/hobo_group.log"); + fileHandler.setFormatter(new SimpleFormatter()); + logger.addHandler(fileHandler); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to create logger", e); + } + return logger; + } + + private void logEating() { + logger.info("Hobos are eating"); + } + void eat() { + logEating(); int[] ingredientsCount = ConfigReader.getInstance().getIngredientsCount(); for (int i = 0; i < ingredients.length; i++) { ingredients[i] -= ingredientsCount[i]; @@ -79,7 +102,7 @@ public void run() { eatingBarrier.await(); } } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); + logger.log(Level.SEVERE, "Thread interrupted", e); } } -} +} \ No newline at end of file diff --git a/lab-02/by/nrydo/docks_and_hobos/Ship.java b/lab-02/by/nrydo/docks_and_hobos/Ship.java index e8d1133..192ea39 100644 --- a/lab-02/by/nrydo/docks_and_hobos/Ship.java +++ b/lab-02/by/nrydo/docks_and_hobos/Ship.java @@ -17,6 +17,10 @@ public int getCargoType() { return cargoType; } + public String getTypeName() { + return ConfigReader.getInstance().getCargoTypes()[cargoType]; + } + public int take(int x) { if (store > x) { store -= x; diff --git a/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java b/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java index 0bdd4e7..3a716b1 100644 --- a/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java +++ b/lab-02/by/nrydo/docks_and_hobos/ShipGenerator.java @@ -1,12 +1,30 @@ package by.nrydo.docks_and_hobos; import java.util.Random; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; public class ShipGenerator implements Runnable { private final Tunnel tunnel; + private final Logger logger; public ShipGenerator(Tunnel tunnel) { this.tunnel = tunnel; + this.logger = createLogger(); + } + + private Logger createLogger() { + Logger logger = Logger.getLogger(ShipGenerator.class.getName()); + try { + FileHandler fileHandler = new FileHandler("log/ship_generator.log"); + fileHandler.setFormatter(new SimpleFormatter()); + logger.addHandler(fileHandler); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to create logger", e); + } + return logger; } @Override @@ -14,10 +32,12 @@ public void run() { ConfigReader config = ConfigReader.getInstance(); while (true) { try { - tunnel.addShip(generateShip()); + Ship ship = generateShip(); + tunnel.addShip(ship); + logShipGeneration(ship); Thread.sleep(config.getGeneratingTime() * 1000L); } catch (InterruptedException e) { - e.printStackTrace(); + logger.log(Level.SEVERE, "Thread interrupted", e); } } } @@ -31,4 +51,9 @@ private Ship generateShip() { int cargoType = random.nextInt(config.getCargoTypes().length); return new Ship(capacity, cargoType); } -} + + private void logShipGeneration(Ship ship) { + String message = String.format("Generated ship: capacity=%d, cargoType=%d", ship.getStore(), ship.getCargoType()); + logger.info(message); + } +} \ No newline at end of file diff --git a/lab-02/by/nrydo/docks_and_hobos/Tunnel.java b/lab-02/by/nrydo/docks_and_hobos/Tunnel.java index c5ad4d8..483ac31 100644 --- a/lab-02/by/nrydo/docks_and_hobos/Tunnel.java +++ b/lab-02/by/nrydo/docks_and_hobos/Tunnel.java @@ -3,22 +3,42 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; public class Tunnel { private final Semaphore placeSemaphore; private final Semaphore shipSemaphore; private final Queue ships; + private final Logger logger; public Tunnel() { - placeSemaphore = new Semaphore(ConfigReader.getInstance().getMaxShips()); + ConfigReader config = ConfigReader.getInstance(); + placeSemaphore = new Semaphore(config.getMaxShips()); shipSemaphore = new Semaphore(0); ships = new ConcurrentLinkedQueue<>(); + logger = createLogger(); + } + + private Logger createLogger() { + Logger logger = Logger.getLogger(Tunnel.class.getName()); + try { + FileHandler fileHandler = new FileHandler("log/tunnel.log"); + fileHandler.setFormatter(new SimpleFormatter()); + logger.addHandler(fileHandler); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to create logger", e); + } + return logger; } public void addShip(Ship ship) { if (placeSemaphore.tryAcquire()) { ships.add(ship); shipSemaphore.release(); + logShipAdded(ship); } } @@ -27,9 +47,19 @@ public Ship getShip() { shipSemaphore.acquire(); Ship ship = ships.poll(); placeSemaphore.release(); + logShipRemoved(ship); return ship; } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Thread interrupted", e); throw new RuntimeException(e); } } -} + + private void logShipAdded(Ship ship) { + logger.info(String.format("Ship added to the tunnel: capacity=%d, cargoType=%s", ship.getStore(), ship.getTypeName())); + } + + private void logShipRemoved(Ship ship) { + logger.info(String.format("Ship removed from the tunnel: capacity=%d, cargoType=%s", ship.getStore(), ship.getTypeName())); + } +} \ No newline at end of file diff --git a/lab-02/log/dock.log b/lab-02/log/dock.log new file mode 100644 index 0000000..ae65130 --- /dev/null +++ b/lab-02/log/dock.log @@ -0,0 +1,10 @@ +дек. 27, 2023 8:08:18 AM by.nrydo.docks_and_hobos.Dock logCargoUnloading +INFO: Unloaded cargo: quantity=5, type=Cheese +дек. 27, 2023 8:08:23 AM by.nrydo.docks_and_hobos.Dock logCargoUnloading +INFO: Unloaded cargo: quantity=2, type=Bread +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Dock logCargoUnloading +INFO: Unloaded cargo: quantity=4, type=Cheese +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Dock logCargoUnloading +INFO: Unloaded cargo: quantity=5, type=Meat +дек. 27, 2023 8:08:38 AM by.nrydo.docks_and_hobos.Dock logCargoUnloading +INFO: Unloaded cargo: quantity=4, type=Meat diff --git a/lab-02/log/hobo.log b/lab-02/log/hobo.log new file mode 100644 index 0000000..93923f4 --- /dev/null +++ b/lab-02/log/hobo.log @@ -0,0 +1,26 @@ +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:27 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:30 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:31 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat diff --git a/lab-02/log/hobo.log.1 b/lab-02/log/hobo.log.1 new file mode 100644 index 0000000..93923f4 --- /dev/null +++ b/lab-02/log/hobo.log.1 @@ -0,0 +1,26 @@ +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:27 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:30 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:31 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat diff --git a/lab-02/log/hobo.log.2 b/lab-02/log/hobo.log.2 new file mode 100644 index 0000000..93923f4 --- /dev/null +++ b/lab-02/log/hobo.log.2 @@ -0,0 +1,26 @@ +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:21 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Bread +дек. 27, 2023 8:08:24 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:27 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:30 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:31 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Cheese +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Hobo stealIngredient +INFO: Stole ingredient: Meat diff --git a/lab-02/log/hobo_group.log b/lab-02/log/hobo_group.log new file mode 100644 index 0000000..22ae530 --- /dev/null +++ b/lab-02/log/hobo_group.log @@ -0,0 +1,2 @@ +дек. 27, 2023 8:08:36 AM by.nrydo.docks_and_hobos.HoboGroup logEating +INFO: Hobos are eating diff --git a/lab-02/log/ship_generator.log b/lab-02/log/ship_generator.log new file mode 100644 index 0000000..41e0540 --- /dev/null +++ b/lab-02/log/ship_generator.log @@ -0,0 +1,10 @@ +дек. 27, 2023 8:08:18 AM by.nrydo.docks_and_hobos.ShipGenerator logShipGeneration +INFO: Generated ship: capacity=5, cargoType=1 +дек. 27, 2023 8:08:23 AM by.nrydo.docks_and_hobos.ShipGenerator logShipGeneration +INFO: Generated ship: capacity=2, cargoType=0 +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.ShipGenerator logShipGeneration +INFO: Generated ship: capacity=4, cargoType=1 +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.ShipGenerator logShipGeneration +INFO: Generated ship: capacity=5, cargoType=2 +дек. 27, 2023 8:08:38 AM by.nrydo.docks_and_hobos.ShipGenerator logShipGeneration +INFO: Generated ship: capacity=0, cargoType=2 diff --git a/lab-02/log/tunnel.log b/lab-02/log/tunnel.log new file mode 100644 index 0000000..5700f0e --- /dev/null +++ b/lab-02/log/tunnel.log @@ -0,0 +1,20 @@ +дек. 27, 2023 8:08:18 AM by.nrydo.docks_and_hobos.Tunnel logShipAdded +INFO: Ship added to the tunnel: capacity=5, cargoType=Cheese +дек. 27, 2023 8:08:18 AM by.nrydo.docks_and_hobos.Tunnel logShipRemoved +INFO: Ship removed from the tunnel: capacity=5, cargoType=Cheese +дек. 27, 2023 8:08:23 AM by.nrydo.docks_and_hobos.Tunnel logShipAdded +INFO: Ship added to the tunnel: capacity=2, cargoType=Bread +дек. 27, 2023 8:08:23 AM by.nrydo.docks_and_hobos.Tunnel logShipRemoved +INFO: Ship removed from the tunnel: capacity=2, cargoType=Bread +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Tunnel logShipAdded +INFO: Ship added to the tunnel: capacity=4, cargoType=Cheese +дек. 27, 2023 8:08:28 AM by.nrydo.docks_and_hobos.Tunnel logShipRemoved +INFO: Ship removed from the tunnel: capacity=4, cargoType=Cheese +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Tunnel logShipAdded +INFO: Ship added to the tunnel: capacity=5, cargoType=Meat +дек. 27, 2023 8:08:33 AM by.nrydo.docks_and_hobos.Tunnel logShipRemoved +INFO: Ship removed from the tunnel: capacity=5, cargoType=Meat +дек. 27, 2023 8:08:38 AM by.nrydo.docks_and_hobos.Tunnel logShipRemoved +INFO: Ship removed from the tunnel: capacity=4, cargoType=Meat +дек. 27, 2023 8:08:38 AM by.nrydo.docks_and_hobos.Tunnel logShipAdded +INFO: Ship added to the tunnel: capacity=4, cargoType=Meat