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

标签 java multithreading concurrency thread-safety deadlock

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

There is a bar in which smoking and non-smoking customers go. The bar has a limited number of seats for customers. Smoking and non-smoking customers can't be present in the bar at the same time. Every customer spends some time traveling to the bar, then enters and spends some time in the bar and finally leaves, freeing his seat for other customers waiting to get in. After the smoking customers have left the bar, the air inside needs to be refreshed so that non-smoking customers can come.

Create a simple simulation of this problem using threads synchronization methods in Java and make sure deadlock doesn't occur.

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

这是代码:

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();
        }
    }
}

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

最佳答案

我创建了 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(); 
 } 
}

关于java - 无法解决与Java Threads相关的教科书示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13653576/

相关文章:

JavaScript 框架和 Java EE

iOS - 从一台设备向另一台设备流式传输和接收音频以一个仅发送而另一个仅接收结束

java - 可迭代的java列表循环并发问题

java - 为什么 ConcurrentSkipListSet.contains 需要比较器而不是等于

Java guava CharMatcher.matchesAnyOf 出现奇怪的编译错误

java - servicemix 4.5 NoInitialContextException

c - 为什么这段代码不是确定性的?

线程可以跟踪进程吗?

java - java中的异步处理

Google Play Console 中的 java.lang.RuntimeException 应用程序崩溃