I'm trying to solve the following problem in 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.
What I could come up with was the following code. I have one problem though - how to implement the condition that the bar needs to be locked for the time needed to refresh its air?
This is the code:
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();
}
}
Then class Customer:
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);
}
}
And finally the main() method:
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();
}
}
}
How do I lock the bar for air refreshing?
I have created a modified version of Magee & Kramer's example about red & blue cars on a bridge. See here (http://flylib.com/books/en/2.752.1.48/1/). I have added the TIME_TO_CLEAR_AIR and MAX_PATRONS stuff. Should be pretty close to what you want. Rename variables to suit. Call the appropriate enter/exit method as per customer type.
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With