3

我正在尝试在 Java 中解决以下问题:

有一个酒吧,吸烟和不吸烟的顾客都可以去。酒吧为顾客提供的座位数量有限。吸烟和不吸烟的顾客不能同时出现在酒吧里。每个顾客都会花一些时间去酒吧,然后进入,在酒吧里呆一段时间,最后离开,腾出座位让其他等待进入的顾客。吸烟的顾客离开酒吧后,需要更新里面的空气这样不吸烟的顾客就可以来了。

使用 Java 中的线程同步方法创建此问题的简单模拟,并确保不会发生死锁。

我能想出的是以下代码。我有一个问题 -如何实现需要在刷新空气所需的时间内锁定酒吧的条件?

这是代码:

class Bar {
    int maxP;
    int curP;
    String state;

    public Bar(int maxP) {
        this.maxP = maxP;
        curP = 0;
        state = "none";
    }
    public synchronized void enterBar(Customer customer) {
        if(state == "none") {
            state = customer.smokingStatus;
        }
        while((curP == maxP) || state != customer.smokingStatus) {
            System.out.println(customer.name+" " + customer.smokingStatus + " is waiting to enter the bar. ");
            try {
                wait();
                if(curP == 0 && state == "none") {
                    state = customer.smokingStatus;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        curP++;
        System.out.println(customer.name +" "+ customer.smokingStatus + " enters the bar and relaxes. ");

    }
    public synchronized void leaveBar(Customer customer) {
        curP--;
        if(curP == 0) {
                 state = "none";
             }
        System.out.println(customer.name +" " + customer.smokingStatus + " stops relaxing and leaves the bar.");
        notifyAll();
    }
}

然后类客户:

class Customer extends Thread {
    String name;
    String smokingStatus;
    Bar bar;

    public Customer(String name, String smoker, Bar bar) {
        this.name = name;
        this.smokingStatus = smoker;
        this.bar = bar;
    }
    public void run() {
        System.out.println(this.name + " is traveling to the bar.");
        try {
            sleep((int)(Math.random()*1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        bar.enterBar(this);
        try {
            sleep((int)(Math.random()*5000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (this.smokingStatus.equals("smoker")){
            System.out.println("After I've been here the bar's air needs some refreshing.");
            try {
                sleep((int)(Math.random()*2000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        bar.leaveBar(this);
    }
}

最后是 main() 方法:

class MainApp {
    public static void main(String args[]) {
        Bar s = new Bar(5);
        for(int i = 0; i < 10; i++) {
            String smokingStatus;
            smokingStatus = Math.random() > 0.5 ? "smoker" : "nonsmoker";
            (new Customer("Customer " + i, smokingStatus, s)).start();
        }
    }
}

如何锁定酒吧以清新空气?

4

2 回答 2

2

我创建了 Magee & Kramer 关于桥上红色和蓝色汽车的示例的修改版本。请参阅此处(http://flylib.com/books/en/2.752.1.48/1/)。我添加了 TIME_TO_CLEAR_AIR 和 MAX_PATRONS 的东西。应该非常接近你想要的。重命名变量以适应。根据客户类型调用适当的进入/退出方法。

public class SafeBar {

 // smokers in the bar
 private int smokers = 0; 

 private int MAX_PATRONS = 20;

 // non-smokers in the bar
 private int nonSmokers = 0; 

 // last time a smoker left the bar
 private long lastSmoke = 0;
 private long TIME_TO_CLEAR_AIR = 10000; // 10 seconds

 synchronized void smokerEnter() throws InterruptedException { 

    while (nonSmokers>0||smokers==MAX_PATRONS) { 
        wait();
    }

    ++smokers; 
 } 

 synchronized void smokerExit(){ 
    --smokers; 
    if (smokers==0) lastSmoke = new Date().getTime();
    notifyAll(); 
 } 

 synchronized void nonSmokerEnter() throws InterruptedException { 

    long checkTime = 0;
    while (smokers>0||nonSmokers==MAX_PATRONS||(checkTime = new Date().getTime()) - lastSmoke < TIME_TO_CLEAR_AIR) {
        if (checkTime - lastSmoke < TIME_TO_CLEAR_AIR)
            wait(TIME_TO_CLEAR_AIR - (checkTime - lastSmoke));
        else 
            wait(); 
    }

    ++nonSmokers; 
 } 

 synchronized void nonSmokerExit(){ 
    --nonSmokers; 
    notifyAll(); 
 } 
}
于 2012-11-30T23:20:38.347 回答
1

在该leaveBar(Customer)方法中,如果离开酒吧的顾客是吸烟者并且是最后一个,则启动一个新线程,该线程会休眠一段时间(刷新时间),最后告诉酒吧空气新鲜。一旦空气新鲜,然后打电话notifyAll()让下一位顾客进入酒吧。

于 2012-11-30T21:48:18.690 回答