-
Notifications
You must be signed in to change notification settings - Fork 23
Shurov lab-02 #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Shurov lab-02 #41
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.logging.Logger; | ||
|
|
||
| public class Bay implements Runnable{ | ||
| private static final Logger logger = LoggerUtil.getLogger(); | ||
| Tunnel tunnel_; | ||
| ArrayList<Dock> docks_; | ||
| HobosCamp hobosCamp_; | ||
|
|
||
| public class HobosCamp implements Runnable { | ||
| HashMap<String, Double> portionIngredients_ = new HashMap<>(); | ||
| volatile HashMap<String, Double> collectedIngredients = new HashMap<>(); | ||
| ArrayList<Hobo> hobos_ = new ArrayList<>(); | ||
|
|
||
| void allHobosEating() throws InterruptedException { | ||
| for (int i = 0; i < hobos_.size(); ++i) { | ||
| hobos_.get(i).eat(); | ||
| } | ||
| } | ||
|
|
||
| public class Hobo implements Runnable { | ||
| Integer EATING_TIME = 20000; | ||
| Integer STEALING_TIME = 1000; | ||
|
|
||
| void eat() throws InterruptedException { | ||
| Thread.sleep(EATING_TIME); | ||
| } | ||
|
|
||
| void steal(String ingredient) { | ||
| boolean cargoStolen = false; | ||
| while (!cargoStolen) { | ||
| for (int i = 0; i < docks_.size(); ++i) { | ||
| if (docks_.get(i).getCargoCapacity(ingredient) != 0) { | ||
| docks_.get(i).stealCargo(ingredient); | ||
| cargoStolen = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| while (true) { | ||
| synchronized (this) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем здесь синхронизация по |
||
| if (!allIngredientsCollected()) { | ||
| for (String ingredient : portionIngredients_.keySet()) { | ||
| if (portionIngredients_.get(ingredient) - collectedIngredients.get(ingredient) != 0) { | ||
| collectedIngredients.put(ingredient, collectedIngredients.get(ingredient) + 1); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А вот тут уже могут быть гонки между |
||
| steal(ingredient); | ||
| logger.info("stolen " + ingredient + " amount = 1"); | ||
| logger.info("collected ingredients = " + collectedIngredients); | ||
| logger.info("recipe ingredients = " + portionIngredients_ + "\n"); | ||
| System.out.println(); | ||
| System.out.println("HOBOS CAMP: stolen = " + ingredient + ", amount = 1"); | ||
| System.out.println("HOBOS CAMP: collected ingredients: " + collectedIngredients); | ||
| System.out.println("HOBOS CAMP: recipe ingredients: " + portionIngredients_); | ||
| System.out.println(); | ||
| try { | ||
| Thread.sleep(STEALING_TIME); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| try { | ||
| logger.info("Now hobos start eating. Eating time = " + EATING_TIME / 1000 + " seconds\n"); | ||
| System.out.println("HOBOS CAMP: Now hobos start eating. Eating time = " + EATING_TIME / 1000 + " seconds\n"); | ||
| allHobosEating(); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| HobosCamp(Integer hobosAmount) { | ||
| if (hobosAmount < 3) { | ||
| hobosAmount = 3; | ||
| } | ||
| portionIngredients_.put("cocaine", 2.0); | ||
| portionIngredients_.put("heroin", 2.0); | ||
| portionIngredients_.put("marijuana", 2.0); | ||
| portionIngredients_.put("pineapple", 1.0); | ||
|
|
||
| collectedIngredients.put("cocaine", 0.0); | ||
| collectedIngredients.put("heroin", 0.0); | ||
| collectedIngredients.put("marijuana", 0.0); | ||
| collectedIngredients.put("pineapple", 0.0); | ||
|
|
||
| for (int i = 0; i < hobosAmount - 2; ++i) { | ||
| Hobo hobo = new Hobo(); | ||
| hobos_.add(hobo); | ||
| } | ||
| } | ||
|
|
||
| boolean allIngredientsCollected() { | ||
| for (String ingredient : portionIngredients_.keySet()) { | ||
| if ((double)portionIngredients_.get(ingredient) != (double)collectedIngredients.get(ingredient)) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Почему тут каст к |
||
| return false; | ||
| } | ||
| } | ||
| for (String ingredient : collectedIngredients.keySet()) { | ||
| collectedIngredients.put(ingredient, 0.0); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| for (int i = 0; i < hobos_.size(); ++i) { | ||
| Thread hubbabubba = new Thread(hobos_.get(i)); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||
| hubbabubba.start(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public Bay(int dockAmount, Tunnel tunnel) { | ||
| tunnel_ = tunnel; | ||
| docks_ = new ArrayList<>(); | ||
|
|
||
|
|
||
| for (int i = 0; i < dockAmount; ++ i) { | ||
| Dock dock = new Dock(1, 20); | ||
| Thread thread = new Thread(dock); | ||
| thread.start(); | ||
| docks_.add(dock); | ||
| } | ||
| hobosCamp_ = new HobosCamp(3); | ||
| Thread hobosCamp = new Thread(hobosCamp_); | ||
| hobosCamp.start(); | ||
| } | ||
| @Override | ||
| public void run() { | ||
| try { | ||
| Thread.sleep(1000); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| while (true) { | ||
| for (Dock dock : docks_) { | ||
| while (dock.shipIsNull()) { | ||
| try { | ||
| Ship ship = tunnel_.getShip(); | ||
| dock.setShip(ship); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
| import java.util.HashMap; | ||
| import java.util.logging.Logger; | ||
|
|
||
| public class Dock implements Runnable{ | ||
| private static final Logger logger = LoggerUtil.getLogger(); | ||
| double unloadingAmountPerSecond_; | ||
| Ship unloadingShip_; | ||
| HashMap<String, Double> storageCapacity_ = new HashMap<>(); | ||
| HashMap<String, Double> maximumStorageCapacity_ = new HashMap<>(); | ||
| public Dock (double unloadingSpeed, double maximumStorageCapacity) { | ||
| unloadingAmountPerSecond_ = unloadingSpeed; | ||
| storageCapacity_.put("cocaine", 0.0); | ||
| storageCapacity_.put("heroin", 0.0); | ||
| storageCapacity_.put("marijuana", 0.0); | ||
| storageCapacity_.put("pineapple", 0.0); | ||
|
|
||
| maximumStorageCapacity_.put("cocaine", maximumStorageCapacity); | ||
| maximumStorageCapacity_.put("heroin", maximumStorageCapacity); | ||
| maximumStorageCapacity_.put("marijuana", maximumStorageCapacity); | ||
| maximumStorageCapacity_.put("pineapple", maximumStorageCapacity); | ||
|
|
||
| unloadingShip_ = null; | ||
| } | ||
|
|
||
| synchronized void setShip (Ship ship) { | ||
| unloadingShip_ = ship; | ||
| } | ||
|
|
||
| Double getCargoCapacity(String cargoType) { | ||
| return storageCapacity_.get(cargoType); | ||
| } | ||
|
|
||
| void stealCargo(String cargoType) { | ||
| storageCapacity_.put(cargoType, storageCapacity_.get(cargoType) - 1); | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| while (true) { | ||
| synchronized (this) { | ||
| if (unloadingShip_ != null) { | ||
| while (unloadingShip_.getCapacity() > 0) { | ||
| double canBeUnloaded = unloadingShip_.unload(unloadingAmountPerSecond_); | ||
| if (storageCapacity_.get(unloadingShip_.getCargoType()) + unloadingAmountPerSecond_ < maximumStorageCapacity_.get(unloadingShip_.getCargoType())) { | ||
| storageCapacity_.put(unloadingShip_.getCargoType(), storageCapacity_.get(unloadingShip_.getCargoType()) + canBeUnloaded); | ||
| } | ||
|
Comment on lines
+45
to
+47
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут же может произойти зацикливание, если товара больше чем нужно и его никак не смогту разгрузить, то сюда не сможет зайти другой корабаль. |
||
| try { | ||
| Thread.sleep(1000); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| logger.info("Ship successfully unloaded, dock free\n"); | ||
| System.out.println("DOCK: Ship successfully unloaded, dock free"); | ||
| unloadingShip_ = null; | ||
| } else { | ||
| continue; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| boolean shipIsNull() { | ||
| return unloadingShip_ == null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.logging.*; | ||
|
|
||
| public class LoggerUtil { | ||
| private static final Logger logger = Logger.getLogger(LoggerUtil.class.getName()); | ||
| private static final Handler fileHandler; | ||
|
|
||
| static { | ||
| try { | ||
| logger.setUseParentHandlers(false); | ||
| fileHandler = new FileHandler("lab-02/logs/app.log"); | ||
| fileHandler.setFormatter(new SimpleFormatter()); | ||
| logger.addHandler(fileHandler); | ||
| } catch (Exception e) { | ||
| throw new ExceptionInInitializerError("Error initializing logger: " + e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| public static Logger getLogger() { | ||
| return logger; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import java.util.logging.Logger; | ||
| import java.io.IOException; | ||
| import java.util.logging.*; | ||
|
|
||
| public class Main { | ||
| private static final Logger logger = LoggerUtil.getLogger(); | ||
| public static void main(String[] args) { | ||
|
|
||
|
|
||
| Tunnel tunnel = new Tunnel(3); | ||
|
|
||
| ShipGenerator shipGenerator = new ShipGenerator(tunnel); | ||
| Thread shipGeneratorThread = new Thread(shipGenerator); | ||
|
|
||
| Integer dockAmount = 4; | ||
|
Comment on lines
+12
to
+17
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| logger.info("Docks amount = " + dockAmount + "\n"); | ||
| System.out.println("MAIN: DOCKS AMOUNT: " + dockAmount); | ||
| Bay bay = new Bay(dockAmount, tunnel); | ||
| Thread bayThread = new Thread(bay); | ||
|
|
||
| shipGeneratorThread.start(); | ||
| bayThread.start(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import javax.swing.*; | ||
|
|
||
| public class Ship { | ||
| private double capacity_; | ||
| private String cargo_type_; | ||
| public Ship(double capacity, String cargo_type) { | ||
| capacity_ = capacity; | ||
| cargo_type_ = cargo_type; | ||
| } | ||
|
|
||
| double getCapacity() { | ||
| return capacity_; | ||
| } | ||
| String getCargoType() {return cargo_type_;} | ||
|
|
||
| double unload(double unloadAmount) { | ||
| if (capacity_ - unloadAmount >= 0 ) { | ||
| capacity_ -= unloadAmount; | ||
| return unloadAmount; | ||
| } else { | ||
| double tmp = capacity_; | ||
| capacity_ = 0; | ||
| return tmp; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import java.util.*; | ||
| import java.util.logging.Logger; | ||
|
|
||
| public class ShipGenerator implements Runnable { | ||
| private static final Logger logger = LoggerUtil.getLogger(); | ||
| Tunnel tunnel_; | ||
| double shipCapacity = 6; | ||
| ArrayList<String> cargoTypes = new ArrayList<>(List.of("cocaine", "heroin", "marijuana", "pineapple")); | ||
| int generationType = 1000; | ||
| public ShipGenerator(Tunnel tunnel) { | ||
| tunnel_ = tunnel; | ||
| } | ||
| @Override | ||
| public void run() { | ||
| while (true) { | ||
| Random random = new Random(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем на каждую итерацию цикла создавать новый инстанс рандома? |
||
| int index = random.nextInt(cargoTypes.size()); | ||
| Ship ship = new Ship(shipCapacity, cargoTypes.get(index)); | ||
| logger.info("Generated new ship\n"); | ||
| System.out.println("SHIP GENERATOR: Generated new ship"); | ||
| tunnel_.addShip(ship); | ||
| try { | ||
| Thread.sleep(generationType); | ||
| } catch (InterruptedException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package by.MikhailShurov.docks_and_hobos; | ||
|
|
||
| import java.util.ArrayDeque; | ||
| import java.util.Queue; | ||
| import java.util.logging.Logger; | ||
|
|
||
| public class Tunnel implements Runnable{ | ||
| private static final Logger logger = LoggerUtil.getLogger(); | ||
| Queue<Ship> tunnel_; | ||
| boolean someDocksWereBlocked = false; | ||
| int maxShips_; | ||
| public Tunnel (int maxShips) { | ||
| tunnel_ = new ArrayDeque<>(); | ||
| maxShips_ = maxShips; | ||
| } | ||
|
|
||
| public void addShip(Ship ship) { | ||
| if (tunnel_.size() < maxShips_) { | ||
| tunnel_.add(ship); | ||
| logger.info("Ship added to tunnel. Tunnel size = " + tunnel_.size() + "\n"); | ||
| System.out.println("TUNNEL: Ship added, tunnel size: " + tunnel_.size()); | ||
| } else { | ||
| logger.info("Ship successfully sank\n"); | ||
| System.out.println("TUNNEL: Ship successfully sank"); | ||
| } | ||
| } | ||
|
Comment on lines
+17
to
+26
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут могут возникнуть гонки из-за того что этот метод не синхронизирован, и происходит работа из нескольких потоков с |
||
|
|
||
| public synchronized Ship getShip() throws InterruptedException { | ||
| if (tunnel_.isEmpty()) { | ||
| return null; | ||
| } | ||
| Ship ship = tunnel_.remove(); | ||
| logger.info("Ship was moved to dock. Tunnel size = " + tunnel_.size() + "\n"); | ||
| System.out.println("TUNNEL: Ship removed, tunnel size:" + tunnel_.size()); | ||
| return ship; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| while (true) { | ||
| if (!tunnel_.isEmpty() && someDocksWereBlocked) { | ||
| someDocksWereBlocked = false; | ||
| tunnel_.notifyAll(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Почему тут в
Double?