Не работает wait в многопоточке (Thread)

Добрый день. Уже несколько дней пытаюсь разобраться, но не получается.
Суть задания: реализую магазин автомобилей, где покупатель приходит в магазин авто и ждет пока завод выпустит авто, чтобы на нем уехать. Пока честную очередь не хочу реализовывать, но суть вопроса будет не в этом.
Ещё пару условий для понимания:

  1. Каждый ключевой этап должен сопровождаться выводом в консоль текущего статуса, например: Производитель Toyota выпустил 1 автомобиль
  2. Должно быть несколько потоков-покупателей, которые будут желать несколько раз купить машину. Производитель выпускает по 1 машине. Программу можно завершать после продажи 10 машин

Проблема: всё работает, кроме главного, где покупатель ждет в очереди, а потом покупает машину. Либо, например, покупатель # 2 доходит до метода waitForCar , где пишется “There are NO car left” , но в итоге покупатель не покупает и остается без покупки… Либо покупатель (как сейчас в редакции кода) не доходит до метода waitForCar … что не реализует саму идею ожидания.

Помогите, пожалуйста, что не так в классе ShowRoom… Скорее всего надо что-то сделать с методом waitForCar и как-то его синхронизировать (всяко разно пробовал, но не получается)…

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
public class Main {
    public static List<Thread> mThreadList;
 
    public static void main(String[] args) throws IOException {
 
        Manufactured manufactured = new Manufactured("Toyota");
        mThreadList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ShowRoom showRoom = new ShowRoom(manufactured);
            mThreadList.add(new Thread(showRoom, "Client #" + (i + 1)));
            mThreadList.get(i).start();
            new Thread(() -> manufactured.sendToShop(showRoom), manufactured.toString()).start();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
import java.util.ArrayList;
import java.util.List;
 
class Manufactured {
private String name;
 
    public Manufactured(String name) {
        this.name = name;
    }
 
    public synchronized void sendToShop(ShowRoom showRoom) {
        try {
            System.out.format("Factory has been created %s  1 car!\n", name);
            Thread.sleep(1000);
            showRoom.addCar(new CreateCar(this));
            System.out.format("There are %s %s car(s) left\n", showRoom.getNoOfCars(),name);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
 
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
class ShowRoom implements Runnable {
    Manufactured manufactured;
    private  static final List<CreateCar> cars = new ArrayList<>();
 
    public ShowRoom(Manufactured manufactured) {
        this.manufactured = manufactured;
    }
 
    public  void run() {
       enterToShowRoom(manufactured);
        if (CarsGreaterThanZero()) {
            getInTheCarAndDrive();
        } else if (CarsEqualToZero()) {
//            waitForCar();
            try {
                while (cars.isEmpty()) {
                    System.out.println("There are NO car left");
                    manufactured.wait();
                }
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getInTheCarAndDrive();
        }
    }
 
    public boolean CarsGreaterThanZero() {
        synchronized (manufactured) {
            if (getNoOfCars() > 0) {
                return true;
            } else {
                return false;
            }
        }
    }
 
    public boolean CarsEqualToZero() {
        synchronized (manufactured) {
            if (getNoOfCars() == 0) {
                return true;
            } else {
                return false;
            }
        }
    }
 
    void waitForCar() {
        synchronized (manufactured) {
            try {
              while (cars.isEmpty()) {
                  System.out.println("There are NO car left");
                  manufactured.wait();
              }
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    void getInTheCarAndDrive() {
        synchronized (manufactured) {
            removeNoOfCars();
            System.out.println(Thread.currentThread().getName()
                    + " has bought, " + getNoOfCars()
                    + " available");
        }
        Random numGen = new Random();
        int r = numGen.nextInt(1000);
        try {
            Thread.sleep(r);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
    }
 
    public synchronized void addCar(CreateCar createCar) {
        cars.add(createCar);
        notify();
    }
 
    public int getNoOfCars() {
        return cars.size();
    }
 
    public void removeNoOfCars() {
        int index = cars.size() - 1;
        cars.remove(index);
    }
    public synchronized void enterToShowRoom(Manufactured manufactured){
        System.out.println(Thread.currentThread().getName()+" entered to showroom");
    }
}
public class CreateCar {
    private final Manufactured manufactured;
 
    public CreateCar(Manufactured manufactured) {
        this.manufactured = manufactured;
    }
}

А где останавливается? Отладчик или вывод могут помочь понять это.

Так нет смысла писать, getNoOfCars() > 0 это и так boolean и его можно вернуть.

вот у меня проблема с отладчиком, когда работаю с многопоточкой))))