Что не так в программе с кораблями?
В классе
ShipGenerator создается рандомное число кораблей. В классе имеется метод
getShip(), который последовательно возвращает созданные корабли.
Исходник
package Ship;
import Ship.types.SizeShip;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ShipGenerator {
private final int MAX_SHIPS;
private final List<Ship> ships = new ArrayList<Ship>();
public ShipGenerator(){
MAX_SHIPS = 5 + (int)(Math.random() * 5);
createShips();
}
public synchronized Ship getShip(){
while (){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(Ship ship : ships){
System.out.println("Корабль: " + ship.getName() + " убыл из БД кораблей!");
return ship;
}
notifyAll();
}
return null;
}
private void createShips(){
// создаем рандомное количество кораблей в диапазоне
for(int i = 0; i < MAX_SHIPS; i++) {
Ship ship = new Ship(getRandomSizeShip());
ships.add(ship);
}
}
private SizeShip getRandomSizeShip(){
Random random = new Random();
return SizeShip.values()[random.nextInt(SizeShip.values().length)];
}
}
Имеется класс
Причал, который является потоком, который принимает на себя корабль и загружает его товаром с помощью вызова метода
add() класса
Ship.
класс Ship
package Ship;
/**
* Класс - Ship (корабль).
*/
import Ship.types.SizeShip;
public class Ship {
{id++;}
private static int id; // идентификационный номер
private final String NAME;
private final SizeShip size;
private int nowGoods = 0; // текущее количество товара
public Ship(SizeShip size){
this.size = size;
this.NAME = "# Ship " + id;
System.out.println("\n" + this.NAME + " was created!" +
"\nSize: " + size.toString() +
"\nCarrying capacity: " + size.getValue() + " (units)");
}
public boolean isFull(){
if(nowGoods < size.getValue())
return false;
else {
System.out.println("[FULL] " + this.NAME + " is fully loaded at " + nowGoods + " (pcs.)");
return true;
}
}
public void add(int count){
this.nowGoods += count;
}
public int getNowGoods(){
return this.nowGoods;
}
public String getName(){
return this.NAME;
}
}
Класс Berth.
/**
* Причал
*/
public class Berth implements Runnable {
{id++;}
private static int id;
private final String NAME;
private final ShipGenerator generator;
private final SizeBerth size;
public Berth(ShipGenerator generator){
this.NAME = "# Berth " + id;
this.generator = generator;
this.size = getRandomSizeBerth();
System.out.println("\n" + this.NAME + " was created!" +
"\nSize: " + size.toString() +
"\nCarrying capacity: " + size.getValue() + " (units)");
new Thread(this, NAME).start();
}
@Override
public void run() {
//while (true){
try {
Ship ship = generator.getShip();
System.out.println("\n" + ship.getName() + " arrived at the " + this.NAME);
while (!ship.isFull()){
ship.add(size.getValue());
System.out.println(ship.getName() + " (" + this.NAME + ") " + " loaded at " + ship.getNowGoods() + " (psc.)");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//}
}
private SizeBerth getRandomSizeBerth(){
Random random = new Random();
return SizeBerth.values()[random.nextInt(SizeShip.values().length - 1)];
}
}
класс ShipGenerator
public class ShipGenerator {
private final int MAX_SHIPS;
private final List<Ship> ships = new ArrayList<Ship>();
public ShipGenerator(){
MAX_SHIPS = 5 + (int)(Math.random() * 5);
createShips();
}
public synchronized Ship getShip(){
while (!ships.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(Ship ship : ships){
ships.remove(ship);
System.out.println("Корабль: " + ship.getName() + " убыл из БД кораблей!");
return ship;
}
notifyAll();
}
return null;
}
private void createShips(){
// создаем рандомное количество кораблей в диапазоне
for(int i = 0; i < MAX_SHIPS; i++) {
Ship ship = new Ship(getRandomSizeShip());
ships.add(ship);
}
}
private SizeShip getRandomSizeShip(){
Random random = new Random();
return SizeShip.values()[random.nextInt(SizeShip.values().length)];
}
}
И, собственно, сам
класс Main, в которос создается 3 (потока) причала (
класс Berth), в которые должы по очереди заезжать корабли. В одном причале одновременно может находиться только один корабль.
класс Main
public class Main {
public static void main(String[] args) {
ShipGenerator shipGenerator = new ShipGenerator();
Berth berth1 = new Berth(shipGenerator);
Berth berth2 = new Berth(shipGenerator);
Berth berth3 = new Berth(shipGenerator);
}
}
На выходе имеем:
Консоль
/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java -javaagent:/snap/intellij-idea-ultimate/228/lib/idea_rt.jar=37661:/snap/intellij-idea-ultimate/228/bin -Dfile.encoding=UTF-8 -classpath /home/n199a/Документы/java/prj/6.4/out/production/6.4 com.company.Main
# Ship 1 was created!
Size: SMALL
Carrying capacity: 20 (units)
# Ship 2 was created!
Size: LARGE
Carrying capacity: 40 (units)
# Ship 3 was created!
Size: MEDIUM
Carrying capacity: 30 (units)
# Ship 4 was created!
Size: SMALL
Carrying capacity: 20 (units)
# Ship 5 was created!
Size: LARGE
Carrying capacity: 40 (units)
# Ship 6 was created!
Size: LARGE
Carrying capacity: 40 (units)
# Ship 7 was created!
Size: LARGE
Carrying capacity: 40 (units)
# Ship 8 was created!
Size: LARGE
Carrying capacity: 40 (units)
# Ship 9 was created!
Size: MEDIUM
Carrying capacity: 30 (units)
# Berth 1 was created!
Size: SMALL
Carrying capacity: 5 (units)
# Berth 2 was created!
Size: MEDIUM
Carrying capacity: 10 (units)
# Berth 3 was created!
Size: SMALL
Carrying capacity: 5 (units)
Создаются корабли и причалы. Тут всё нормально.
Метод
getShip() синхронизирован для потоков.
Вопрос: почему корабли не загружаются?
Пробовал и так, всё равно не получается.
Исходник
public synchronized Ship getShip(){
try {
notifyAll();
for(Ship ship : ships){
System.out.println("Корабль: " + ship.getName() + " убыл из БД кораблей!");
return ship;
}
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
Получается, что выплывает только один и тот же корабль всё время (самый первый). И так бесконечно. Вот консоль:
Консоль
# Ship 1 arrived at the # Berth 1
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
[1]Корабль: # Ship 1 убыл из БД кораблей!
# Ship 1 arrived at the # Berth 3
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
# Ship 1 arrived at the # Berth 2
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
[1]Корабль: # Ship 1 убыл из БД кораблей!
# Ship 1 arrived at the # Berth 3
[1]Корабль: # Ship 1 убыл из БД кораблей!
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
[1]Корабль: # Ship 1 убыл из БД кораблей!
# Ship 1 arrived at the # Berth 2
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
# Ship 1 arrived at the # Berth 1
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
[1]Корабль: # Ship 1 убыл из БД кораблей!
# Ship 1 arrived at the # Berth 3
[1]Корабль: # Ship 1 убыл из БД кораблей!
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
[1]Корабль: # Ship 1 убыл из БД кораблей!
# Ship 1 arrived at the # Berth 2
[FULL] # Ship 1 is fully loaded at 40 (pcs.)
Process finished with exit code 130 (interrupted by signal 2: SIGINT)