Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/Bay.java
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<>();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему тут в Double?

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) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем здесь синхронизация по this? С этим классом ты нигде больше не работаешь.

if (!allIngredientsCollected()) {
for (String ingredient : portionIngredients_.keySet()) {
if (portionIngredients_.get(ingredient) - collectedIngredients.get(ingredient) != 0) {
collectedIngredients.put(ingredient, collectedIngredients.get(ingredient) + 1);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А вот тут уже могут быть гонки между collectedIngredients.put и collectedIngredients.get, volatile здесь не поможет.

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)) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему тут каст к double?

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));

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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);
}
}
}
}
}
}
67 changes: 67 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/Dock.java
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

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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;
}
}
24 changes: 24 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/LoggerUtil.java
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;
}
}
26 changes: 26 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/Main.java
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

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все переменные должны задаваться в файле config.json. Путь до этого файла передается аргументов в вашу программу

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();
}
}
28 changes: 28 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/Ship.java
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;
}
}
}
31 changes: 31 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/ShipGenerator.java
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();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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);
}
}
}
}
47 changes: 47 additions & 0 deletions lab-02/by/MikhailShurov/docks_and_hobos/Tunnel.java
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

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут могут возникнуть гонки из-за того что этот метод не синхронизирован, и происходит работа из нескольких потоков с tunnel_.


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();
}
}
}
}
Loading