一餐厅有50个座位可供用餐者就餐,超过50人时只能排队等候,待空出座位方可就餐,如何用管程实现?
public class Restaurant {
/**
* 最大座位数
*/
static private int MAX_SEAT = 50;
/**
* 当前已经来的客人
*/
static private AtomicInteger SEAT_CUSTOMER = new AtomicInteger(0);
/**
* 排队队列
*/
LinkedBlockingQueue SEAT_QUEUE = new LinkedBlockingQueue();
public static void main(String[] args) {
Restaurant restaurant = new Restaurant();
//放入1000个顾客测试 1秒放入一个
Thread customer = new Thread(() -> {
for (int i = 0; i < 500; i++) {
restaurant.customerComIn(System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
customer.start();
Thread customer2 = new Thread(() -> {
for (int i = 0; i < 500; i++) {
restaurant.customerComIn(System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
customer2.start();
//此线程定时移除乘客,代表结账 没2秒执行一次
new Thread(() -> {
while (true) {
restaurant.customerComInLeave();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 顾客离开
*/
private void customerComInLeave() {
synchronized (SEAT_CUSTOMER) {
if (SEAT_CUSTOMER.get() <= 0) {
return;
}
SEAT_CUSTOMER.decrementAndGet();
System.out.println(Thread.currentThread().getName() + "当前离开顾客1位");
//安排队列中的乘客落座
customerSeat();
}
}
/**
* 从队列中安排顾客落座
*/
private void customerSeat() {
while (true) {
//如果没有等待的顾客则返回
if (SEAT_QUEUE.size() == 0) {
System.out.println("没有顾客等待");
return;
}
Object num = SEAT_QUEUE.peek();
if (num != null) {
boolean seatResult = seat(Long.valueOf(num.toString()));
if (seatResult) {
SEAT_CUSTOMER.getAndIncrement();
System.out.println("有顾客结账,队列中的: " + num + "落座;队列中还有人: " + SEAT_QUEUE.toString());
SEAT_QUEUE.remove(num);
} else {
SEAT_QUEUE.add(num);
return;
}
}
}
}
/**
* 顾客来了
* 这地方暂时用一个int 可以改造成一个对象
* 目前只考虑单客人
*
* @return true:代表落座成功,false:代表等待
*/
private boolean customerComIn(Long num) {
synchronized (SEAT_CUSTOMER) {
boolean seatResult = seat(num);
if (seatResult) {
SEAT_CUSTOMER.getAndIncrement();
} else {
SEAT_QUEUE.add(num);
}
return seatResult;
}
}
private boolean seat(Long num) {
//超过50人的时候
if (SEAT_CUSTOMER.get() > MAX_SEAT) {
System.out.println(Thread.currentThread().getName() + "当前人数: " + SEAT_CUSTOMER.get() + ";请等待: " + SEAT_QUEUE.size());
return false;
} else {
System.out.println(Thread.currentThread().getName() + "当前人数: " + SEAT_CUSTOMER.get() + ";请入座");
return true;
}
}
}
运行结果:
Thread-2当前人数: 51;请等待: 17
Thread-0当前人数: 51;请等待: 18
Thread-1当前人数: 51;请等待: 19
Thread-0当前人数: 51;请等待: 20
Thread-1当前人数: 51;请等待: 21
Thread-2当前离开顾客1位
Thread-2当前人数: 50;请入座
有顾客结账,队列中的: 1649695145832落座;队列中还有人:
给餐厅的点餐人数初始化一个0值,每当有人点餐该值加1,有人结账时该值减1,点餐前先获取该值,小于50允许点餐,大于等于50提示餐位已满,请等待
cobegin
process eat_i //i=1,2,3,....,
{
Restaurant.eating();
}
coend
Semaphore semaphore = new Semaphore(50); 加队列
这个需要软硬件结合
第一种,半自动(人工辅助)
50个位置是要输入电脑的,
换位也是要输入电脑的,换位需要注意,没上的菜也要换桌(跟着号码牌即可)
客未满,服务员需要让顾客点单,问清几个人,给个号码牌,如果服务员有PDA,当时就输入,某号码牌坐哪一桌,有几个人。
吃完后,顾客买单,服务员输入,某某号牌买单,根据点单占位数自动得出某桌空出多少个位
自动化
这个没意义,无法真正实施,可能会造成混乱,比如逃单,你都不知道桌子到底空没空。