Я пишу небольшую программу, которая поможет мне узнать многопоточность в java, и я зациклился на том, как реализовать какой-то сценарий.Тема в 2 очередях
Программа имитирует заправочную станцию, в которой также есть кофейня. Я хочу, чтобы иметь возможность создать следующую сценарий:
- добавить человека в очередь на газовый насос.
- в то же время добавить человека в очередь для кассира в кофейне.
- Если очередь человека в очереди на насос прибывает до поворота в очереди кассира, разрешите ему выбрать, что делать (оставайтесь в очереди на кассе и покидайте очередь насоса или наоборот).
Как я могу прыгать между этими двумя состояниями?
До сих пор у меня есть это:
Человек класс
public class Person implements Runnable {
private GasPump pump;
private Cashier cashier;
...
public void pumpGas() throws InterruptedException {
synchronized (this) {
pump.addCarToQueue(this);
wait();
}
synchronized (pump) {
sleep((long) (Math.random() * 5000));
pump.notify();
}
}
public void buyCoffee() throws InterruptedException {
synchronized (this) {
cashier.addCustomerToQueue(this); // standing inline
wait();
}
synchronized (cashier) {
sleep((long) (Math.random() * 5000)); // paying at cashier
cashier.notify();
}
}
...
}
GasPump класс
public class GasPump implements Runnable {
private Queue<Person> cars;
...
@Override
public void run() {
while (gasStation.isOpen()) {
if (!cars.isEmpty()) {
Car firstCar = cars.poll();
if (firstCar != null) {
synchronized (firstCar) {
firstCar.notifyAll();
}
} else {
// ?
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
...
}
И класс кассир
public class Cashier implements Runnable {
private Queue<Person> customers;
...
@Override
public void run() {
while(coffeeHouse.isOpen()){
if(!customers.isEmpty()){
Car firstCustomer = customers.poll();
if(firstCustomer != null){
synchronized (firstCustomer) {
firstCustomer.notifyAll();
}
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
...
}
Должен ли я запускать поток Person после того, как я получу объект из take(), или если все потоки начнутся при вставке в очереди? –
@ Yoni Levy Потоки 'GasPump',' Cashier' и 'Person' должны начинаться после их инициализации; «Человек» должен называть «pumpGas» и «buyCoffee» и «then», '' Person' должен 'спать' (' pumpGas' и 'buyCoffee' должны просто добавить' Person' в соответствующие очереди, они не должны звонить 'wait' или' sleep' или что-то в этом роде; потоки 'GasPump' и' Cashier' должны «прерывать» «Лицо» после его удаления из очереди, чтобы разбудить его, и «Лицо» должно затем проглотить/проигнорировать возникающее исключение. –
@ Yoni Levy Я рекомендую вам использовать [ThreadPoolExecutor] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html), чтобы запустить ваши объекты Person; это приведет к тому, что все ваши объекты «Личность» будут иметь общий пул потоков, а не выделять отдельный поток для каждого «Человека» –