2012-11-30 124 views
3

我试图解决在Java中,以下问题与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(); 
     } 
    } 
} 

怎么锁定了吧空气清新?

+0

你需要专门的“进修”线程,检查离开的客户是否留下不愉快的气味。进入的非吸烟顾客将检查是否存在异味,并且会阻止直到更新线完成它的工作。 –

+0

为了记录我有点讨厌这个问题,这是多线程的一个荒谬的用法,无论作者希望你想出什么锁定机制,在严肃的代码审查中不会持续10秒。 – djechlin

+0

@djechlin:我个人喜欢它。用*工作线程*和*工具栏*替换*客户*通过*连接池*,你有一个更现实,但更抽象的问题。 –

回答

1

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

+0

即使空气不新鲜,新的吸烟者也不能进入吗? – Kevin

+1

我不知道。问老师。如果是我,吸烟者根本不会在酒吧里吸烟:-) –

+0

“吸烟的顾客离开酒吧后,需要更新里面的空气,以便不吸烟的顾客可以来。”不需要清楚地询问该规则仅适用于不吸烟者。 – Kevin

2

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

我不认为这是线程安全的。 'wait'在一个对象上释放一个线程的锁。意思是一个非吸烟者会发现他们必须等待才能进入酒吧,同时新的吸烟者进入酒吧,所以现在非吸烟者肯定不能进入,但他们不会重新检查他们是否可以进入酒吧再次。因此,吸烟者和非吸烟者可以同时在酒吧内。 – Dunes

+0

@Dunes“但他们不重新检查他们是否可以再次进入”。他们绝对如此。看while循环。你提到的情况是不可能的。这个解决方案是线程安全的。 – xagyg

+0

对不起,我想我误解你的代码。 – Dunes