无法解决与Java Threads相关的教科书示例

时间:2012-11-30 21:39:12

标签: java multithreading concurrency thread-safety deadlock

我正在尝试用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();
        }
    }
}

如何锁定空气清新条?

2 个答案:

答案 0 :(得分:2)

我已经创建了Magee&amp; amp;的修改版本。克莱默关于红色&amp; amp;在桥上的蓝色车。见这里(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(); 
 } 
}

答案 1 :(得分:1)

leaveBar(Customer)方法中,如果离开酒吧的顾客是吸烟者并且是最后一个,那么开始一个睡眠一段时间(刷新时间)的新线程,最后告诉酒吧空气清新。空气清新后,请致电notifyAll()让下一位顾客进入吧台。