学到多线程,编了一个简单地电脑城进出货模拟系统。
代码有点长,主要部分如下所述:
有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。
限于篇幅问题,摘录主要代码如下:
--------------------------厂家类---------------------------------------
Java代码

public class Mainboardretailer implements Runnable// 主板厂家 

{ 

 public void run() 

 { 

 while(true) 

 { 

 电脑城.stockMainboard(deliverMB("MSI"));//不断向电脑城供货 

 } 

 } 


 public Mainboard deliverMB(String 主板名) 

 { 

 return 主板; 

 } 


} 

public class Videocardretailer implements Runnable// 显卡厂家 

{ 

 public void run() 

 { 

 while(true) 

 { 

 电脑城.stockVideocard(deliverVC("ATI"));//不断向电脑城供货 

 } 

 } 

 public videocard deliverMB(String 显卡名) 

 { 

 return 显卡; 

 } 


}



-------------------------------------顾客类-------------------------------------------
Java代码

public class customer implements Runnable 

{ 

 public void run() 

 { 

 while(true) 

 { 

 buyVC("ATI"); 

 //顾客不断购买显卡和主板 

 buyMB("MSI"); 

 } 

 } 


}



-----------------------------电脑城类-----------------------------------------
Java代码

public class ComputerCenter 

{ 

 int MAXVCSTORE = 100;//货仓容量 

 int MAXMBSTORE = 100;//货仓容量 

 private static LinkedList<Videocard> VideocardQty = new LinkedList<Videocard>();//显卡货仓 

 private static LinkedList<Mainboard> MainboardQty = new LinkedList<Mainboard>();//主板货仓 


 public synchronized void stockVideocard(Videocard VCname) 

 { 

 if(VideocardQty.size() >= MAXVCSTORE) 

 { 

 System.out.println("ComputerCenter: the VC storage is MAX"); 

 try 

 { 

 wait();//---------------------当存货过多时。通知厂商等待。 

 } catch (InterruptedException e) 

 { 

 e.printStackTrace(); 

 } 

 } 

 VideocardQty.add(VCname); 

 notify();//----------------------------唤醒消费者消费 

 } 


 public synchronized void stockMainboard(Mainboard MBname) 

 { 

 if(MainboardQty.size() >= MAXVCSTORE) 

 { 

 System.out.println("ComputerCenter: the MB storage is MAX"); 

 try 

 { 

 wait();//----------------------当存货过多时。通知厂商等待。 

 } catch (InterruptedException e) 

 { 

 e.printStackTrace(); 

 } 

 } 

 MainboardQty.add(MBname); 

 notify();//-----------------------------唤醒消费者消费 

 } 


 public synchronized Videocard sellVideocard(String VCname) 

 { 

 if(VideocardQty.size() <= 0) 

 { 

 try 

 { 

 wait();//-----------------没有存货时,通知消费者等待 

 }catch(Exception e) 

 { 

 e.printStackTrace(); 

 } 

 } 

 notify();//----------------------------------唤醒厂商 

 return MyVideocard; 

 } 


 public synchronized Mainboard sellMainboard(String MBname) 

 { 

 if(MainboardQty.size() <= 0) 

 { 

 try 

 { 

 wait();//-----------------没有存货时,通知消费者等待 

 }catch(Exception e) 

 { 

 e.printStackTrace(); 

 } 

 } 

 notify();//----------------------------------唤醒厂商 

 return MyMainboard; 

 } 


 public static void main(String[] args) 

 { 

 ComputerCenter MyCC = new ComputerCenter(); 

 new customer(MyCC,"Jack").start(); 

 new customer(MyCC,"Tom").start(); 

 new Mainboardretailer(MyCC).start(); 

 new Videocardretailer(MyCC).start(); 

 } 


}




现在出现了这样的一个问题:
1.如果有两个消费者同时等待,厂家生产后唤醒其中消费者A,消费者A购买完毕后会唤醒消费者B--不合逻辑。
2.如果购买显卡地消费者A在等待,电脑城从主板厂商进货了主板以后会唤醒消费者A。同样的情况也发生在购买主板的消费者B身上。
3.如果两家厂商在等待消费者购买商品,此时消费者A购买了主板,货仓主板数量-1,然后有可能唤醒显卡厂商而没有唤醒主板厂商进行生产。
4.如果两家厂商正在等待消费者购买商品,此时显卡厂商被唤醒后,可能立刻唤醒主板厂商生产主板,令到商品数量超出仓库上限。

我想,有没有什么办法,可以指定唤醒某个线程?如果可以,那问题就容易解决了。

------------------------------------------------------------------------------------------------------------------
问题补充:
xmind 写道
主要问题是 显卡 没了,等显卡送来,主板没了等主板送来。
不能人家来买显卡的,你进来一个主板也通知人家来买。
写了个例子,你看看。
Java代码

class ComputerCenter { 

 private static Object VIDEO = new Object(); 

 private static Object MAINB = new Object(); 

 private static Integer videoN = 10; 

 private static Integer MainbN = 10; 


 public void stockVd() { 

 synchronized(VIDEO) { 

 if(videoN >= 20) { 

 System.out.println("ComputerCenter: the VC storage is MAX"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 System.out.println("ComputerCenter: 厂商送来一块显卡。"); 

 videoN++; 

 VIDEO.notify();//----------------------------唤醒消费者消费 

 } 

 } 


 public void stockMd() { 

 synchronized(MAINB) { 

 if(MainbN >= 20) { 

 System.out.println("ComputerCenter: the MB storage is MAX"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 System.out.println("ComputerCenter: 厂商送来一块主板。"); 

 MainbN++; 

 MAINB.notify();//-----------------------------唤醒消费者消费 

 } 

 } 


 public void sellVd(String name) { 

 synchronized(VIDEO) { 

 if(videoN <= 0) { 

 System.out.println("没有显卡了,等等,马上送来!!!!!!!!!"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块显卡。"); 

 videoN--; 

 VIDEO.notify();//----------------------------------唤醒厂商 

 } 

 } 


 public void sellMd(String name) { 

 synchronized(MAINB) { 

 if(MainbN <= 0) { 

 System.out.println("没有主板了,等等,马上送来!!!!!!!!!!"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块主板。"); 

 MainbN--; 

 MAINB.notify();//----------------------------------唤醒厂商 

 } 

 } 



 public static void main(String[] args) { 

 ComputerCenter MyCC = new ComputerCenter(); 

 new customer(MyCC,"Jack").start(); 

 new customer(MyCC,"Tom").start(); 

 new Md_retailer(MyCC).start(); 

 new Vd_retailer(MyCC).start(); 

 } 

} 


class customer extends Thread { 

 private ComputerCenter cc; 

 private String name; 

 public customer(ComputerCenter cc,String name) { 

 this.cc = cc; 

 this.name = name; 

 } 


 public void run() { 

 while(true) { 

 //try {Thread.sleep(10);} catch (Exception e) {} 

 //顾客不断购买显卡和主板 

 cc.sellVd(name); cc.sellMd(name); 

 } 

 } 

} 

class Md_retailer extends Thread { 

 private ComputerCenter cc; 

 public Md_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockMd(); 

 } 

 } 

} 

class Vd_retailer extends Thread { 

 private ComputerCenter cc; 

 public Vd_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockVd(); 

 } 

 } 

}




注释掉不同地方的 try {Thread.sleep(10);} catch (Exception e) {} 可以模拟不同的情况。


非常感谢您,我修改了一下代码,用synchronized代码块来指定唤醒地对象。但是依然有一个问题:当有2人同时在等待买显卡地时候,厂商送来一块显卡,A买完后,却会唤醒B去买。这里有逻辑错误。该怎么样改进一下呢?
其实还有有种办法解决,就是通过在wait()那里套一个while(iswaiting)来实现唤醒指定地线程。电脑城进货后,改变某个boolean值,唤醒所有线程。那些没有被改变boolean值的线程将被套在while循环里面。这样可以解决问题,但我总觉得怪怪地不自然。

------------------------------------------------------------------------------------------------------------------
问题补充:
xmind 写道
噢,对不起,我是没有考虑这个情况。
你说的那种方法应该能够实现,我等待后再判断的方法试了试,要使,你看看
Java代码

public void sellMd(String name) { 

 synchronized(MAINB) { 

 if(MainbN <= 0) { 

 System.out.println("没有主板了,等等,马上送来!!!!!!!!!!"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 if(MainbN >0) { 

 System.out.println(name + " : 买走一块主板。"+MainbN); 

 MainbN--; 

 } 

 MAINB.notify();//----------------------------------唤醒厂商 

 } 

 } 

}



谢谢您。我觉得呢,这样子看上去是可行的,但还有一点逻辑上的错误。假如A,B都在等待买显卡,此时电脑城获得一块显卡,库存显卡数为1,通知AB其中一个。假设A买到了显卡,显卡库存变为0。此时A唤醒B。B醒来后if判断显卡数不大于0,所以并没有买走显卡,但是他却被唤醒并离开了,也就是说他这次不买显卡了(他本来是想买显卡的,只不过没货,在等待)。并且他离开时通知了电脑城再进一块显卡(如果此时达到库存上线,厂商在等待消费,那么它将被B唤醒而生产显卡,导致电脑城显卡数超出库存)。
这里是不是有点逻辑上的小漏洞呢?大家探讨探讨。

------------------------------------------------------------------------------------------------------------------
问题补充:
hareamao 写道


Java代码

import java.util.ArrayDeque; 


public class StockManager { 

 private final Object producerLock = new Object(); 

 private final Object consumerLock = new Object(); 

 private final int MAX_SIZE = 10; 


 private final ArrayDeque<Product> queue = new ArrayDeque<Product>(); 


 public void stock(Product p) throws InterruptedException { 

 synchronized (producerLock) { 

 if (queue.size() >= MAX_SIZE) { 

 producerLock.wait(); 

 } 

 } 

 synchronized (queue) { 

 queue.add(p); 

 } 

 synchronized (consumerLock) { 

 consumerLock.notify(); 

 } 

 } 


 public synchronized Product purchase() throws InterruptedException { 

 synchronized (consumerLock) { 

 if (queue.size() <= 0) { 

 consumerLock.wait(); 

 } 

 } 

 Product product = null; 

 synchronized (queue) { 

 product = queue.remove(); 

 } 

 synchronized (producerLock) { 

 producerLock.notify(); 

 } 

 return product; 

 } 

}



lz基本的问题就是,厂商和客户等的不是同一把锁,所以要分别对待。然后就简单了。不过我的StockManager看着也不怎么对劲儿。


阁下的方法是,将StockManager分开实例化令厂商解锁时只解在自己队列上排队的顾客,从而避免了唤醒另外一条队的顾客。这样子也可以。thanks。
另外问一句,为什么阁下的代码中这么多final的?

采纳的答案

2010-07-26 hareamao (高级程序员)
没怎么写过多线程,拿来练练手,未必正确。

Java代码

public class Product { 

 private String name; 

 private int serial; 


 public String getName() { 

 return name; 

 } 


 public void setName(String name) { 

 this.name = name; 

 } 


 public int getSerial() { 

 return serial; 

 } 


 public void setSerial(int serial) { 

 this.serial = serial; 

 } 

}



Java代码

import java.util.ArrayDeque; 


public class StockManager { 

 private final Object producerLock = new Object(); 

 private final Object consumerLock = new Object(); 

 private final int MAX_SIZE = 10; 


 private final ArrayDeque<Product> queue = new ArrayDeque<Product>(); 


 public void stock(Product p) throws InterruptedException { 

 synchronized (producerLock) { 

 if (queue.size() >= MAX_SIZE) { 

 producerLock.wait(); 

 } 

 } 

 synchronized (queue) { 

 queue.add(p); 

 } 

 synchronized (consumerLock) { 

 consumerLock.notify(); 

 } 

 } 


 public synchronized Product purchase() throws InterruptedException { 

 synchronized (consumerLock) { 

 if (queue.size() <= 0) { 

 consumerLock.wait(); 

 } 

 } 

 Product product = null; 

 synchronized (queue) { 

 product = queue.remove(); 

 } 

 synchronized (producerLock) { 

 producerLock.notify(); 

 } 

 return product; 

 } 

}



Java代码

import java.util.logging.Logger; 


public class Producer implements Runnable{ 

 private static final Logger log = Logger.getLogger(Producer.class.getName()); 


 private String productName = null; 

 private int serial = 0; 

 private StockManager stockManager; 


 public void setProductName(String productName) { 

 this.productName = productName; 

 } 


 public void setStockManager(StockManager stockManager) { 

 this.stockManager = stockManager; 

 } 


 public Product produce() { 

 final Product p = new Product(); 

 p.setName(productName); 

 p.setSerial(++serial); 

 return p; 

 } 


 @Override 

 public void run() { 

 try { 

 for( int i = 0; i < 20; i++) { 

 deliver(); 

 } 

 Thread.sleep(30 * 1000); 

 while (true) { 

 deliver(); 

 } 

 } catch (InterruptedException e) { 

 e.printStackTrace(); 

 } 

 } 


 private void deliver() throws InterruptedException { 

 final long s = System.currentTimeMillis(); 

 final Product product = produce(); 

 stockManager.stock(product); 

 final long time = System.currentTimeMillis() - s; 

 if (time > 10) { 

 log.info(product.getName() + ", No. " + 

 product.getSerial() + " took " + 

 time + " milli seconds to finish." ); 

 } 

 } 

} 


Java代码 

import java.util.logging.Logger; 


public class Consumer implements Runnable { 

 private static final Logger log = Logger.getLogger(Consumer.class.getName()); 


 private String name; 

 private StockManager[] stockManagers; 


 public void setName(String name) { 

 this.name = name; 

 } 


 public void setStockManagers(StockManager[] stockManagers) { 

 this.stockManagers = stockManagers; 

 } 


 @Override 

 public void run() { 

 for (int i = 0; i < 50; i++) { 

 final double v = Math.random() * stockManagers.length; 

 final int k = (int) Math.floor(v); 

 try { 

 final long s = System.currentTimeMillis(); 

 final Product product = stockManagers[k].purchase(); 

 final long time = System.currentTimeMillis() - s; 

 String l = ""; 

 if (time > 10) { 

 l += "after " + time + " milli seconds of waiting, "; 

 } 

 l += (name + " bought product " + product.getName() 

 + ", serial No. " + product.getSerial()); 

 log.info(l); 

 } catch (InterruptedException e) { 

 e.printStackTrace(); 

 break; 

 } 


 try { 

 Thread.sleep(100); 

 } catch (InterruptedException e) { 

 e.printStackTrace(); 

 break; 

 } 

 } 

 } 

} 


Java代码 

public class Mall { 

 public static void main(String[] args) { 

 final StockManager mb = new StockManager(); 

 final Producer pmb = new Producer(); 

 pmb.setProductName("Motherboard"); 

 pmb.setStockManager(mb); 


 final StockManager vd = new StockManager(); 

 final Producer pvd = new Producer(); 

 pvd.setProductName("Video Card"); 

 pvd.setStockManager(vd); 


 final StockManager[] stockManagers = new StockManager[2]; 

 stockManagers[0] = mb; 

 stockManagers[1] = vd; 


 final Consumer c1 = new Consumer(); 

 c1.setName("C1"); 

 c1.setStockManagers(stockManagers); 


 final Consumer c2 = new Consumer(); 

 c2.setName("C2"); 

 c2.setStockManagers(stockManagers); 


 new Thread(c1).start(); 

 new Thread(c2).start(); 


 try { 

 Thread.sleep(2000); 

 } catch (InterruptedException e) { 

 e.printStackTrace(); 

 } 


 new Thread(pmb).start(); 

 new Thread(pvd).start(); 

 } 

}




提问者对于答案的评价:
解决办法之一.
问题答案可能在这里 → 寻找更多解答

java生产者消费者经典问题
Java 关于线程同步的问题
java多线程 消费者-生产者
我有一个关于多线程编码的问题..
一段关于线程的代码 请教
其他回答

1.消费者由生产唤醒,每次唤醒队列中的一个,A买完就走,不要多管闲事
2.不同的产品在不同的队列中,不要排别人的队
3.4.同2
qinglangee (资深程序员) 2010-07-26
主要问题是 显卡 没了,等显卡送来,主板没了等主板送来。
不能人家来买显卡的,你进来一个主板也通知人家来买。
写了个例子,你看看。
Java代码

class ComputerCenter { 

 private static Object VIDEO = new Object(); 

 private static Object MAINB = new Object(); 

 private static Integer videoN = 10; 

 private static Integer MainbN = 10; 


 public void stockVd() { 

 synchronized(VIDEO) { 

 if(videoN >= 20) { 

 System.out.println("ComputerCenter: the VC storage is MAX"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 System.out.println("ComputerCenter: 厂商送来一块显卡。"); 

 videoN++; 

 VIDEO.notify();//----------------------------唤醒消费者消费 

 } 

 } 


 public void stockMd() { 

 synchronized(MAINB) { 

 if(MainbN >= 20) { 

 System.out.println("ComputerCenter: the MB storage is MAX"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 System.out.println("ComputerCenter: 厂商送来一块主板。"); 

 MainbN++; 

 MAINB.notify();//-----------------------------唤醒消费者消费 

 } 

 } 


 public void sellVd(String name) { 

 synchronized(VIDEO) { 

 if(videoN <= 0) { 

 System.out.println("没有显卡了,等等,马上送来!!!!!!!!!"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块显卡。"); 

 videoN--; 

 VIDEO.notify();//----------------------------------唤醒厂商 

 } 

 } 


 public void sellMd(String name) { 

 synchronized(MAINB) { 

 if(MainbN <= 0) { 

 System.out.println("没有主板了,等等,马上送来!!!!!!!!!!"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块主板。"); 

 MainbN--; 

 MAINB.notify();//----------------------------------唤醒厂商 

 } 

 } 



 public static void main(String[] args) { 

 ComputerCenter MyCC = new ComputerCenter(); 

 new customer(MyCC,"Jack").start(); 

 new customer(MyCC,"Tom").start(); 

 new Md_retailer(MyCC).start(); 

 new Vd_retailer(MyCC).start(); 

 } 

} 


class customer extends Thread { 

 private ComputerCenter cc; 

 private String name; 

 public customer(ComputerCenter cc,String name) { 

 this.cc = cc; 

 this.name = name; 

 } 


 public void run() { 

 while(true) { 

 //try {Thread.sleep(10);} catch (Exception e) {} 

 //顾客不断购买显卡和主板 

 cc.sellVd(name); cc.sellMd(name); 

 } 

 } 

} 

class Md_retailer extends Thread { 

 private ComputerCenter cc; 

 public Md_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockMd(); 

 } 

 } 

} 

class Vd_retailer extends Thread { 

 private ComputerCenter cc; 

 public Vd_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockVd(); 

 } 

 } 

}



注释掉不同地方的 try {Thread.sleep(10);} catch (Exception e) {} 可以模拟不同的情况。
xmind (中级程序员) 2010-07-26
噢,对不起,我是没有考虑这个情况。
你说的那种方法应该能够实现,我等待后再判断的方法试了试,要使,你看看
Java代码

class ComputerCenter { 

 private static Object VIDEO = new Object(); 

 private static Object MAINB = new Object(); 

 private static Integer videoN = 10; 

 private static Integer MainbN = 10; 


 public void stockVd() { 

 synchronized(VIDEO) { 

 if(videoN >= 20) { 

 System.out.println("ComputerCenter: the VC storage is MAX"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 videoN++; 

 System.out.println("ComputerCenter: 厂商送来一块显卡。" + videoN); 

 VIDEO.notify();//----------------------------唤醒消费者消费 

 } 

 } 


 public void stockMd() { 

 synchronized(MAINB) { 

 if(MainbN >= 20) { 

 System.out.println("ComputerCenter: the MB storage is MAX"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 MainbN++; 

 System.out.println("ComputerCenter: 厂商送来一块主板。"+MainbN); 

 MAINB.notify();//-----------------------------唤醒消费者消费 

 } 

 } 


 public void sellVd(String name) { 

 synchronized(VIDEO) { 

 if(videoN <= 0) { 

 System.out.println("没有显卡了,等等,马上送来!!!!!!!!!"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 if(videoN >0) { 

 System.out.println(name + " : 买走一块显卡。"+videoN); 

 videoN--; 

 } 

 VIDEO.notify();//----------------------------------唤醒厂商 

 } 

 } 


 public void sellMd(String name) { 

 synchronized(MAINB) { 

 if(MainbN <= 0) { 

 System.out.println("没有主板了,等等,马上送来!!!!!!!!!!"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 if(MainbN >0) { 

 System.out.println(name + " : 买走一块主板。"+MainbN); 

 MainbN--; 

 } 

 MAINB.notify();//----------------------------------唤醒厂商 

 } 

 } 


 public static void main(String[] args) { 

 ComputerCenter MyCC = new ComputerCenter(); 

 new customer(MyCC,"Jack").start(); 

 new customer(MyCC,"Tom").start(); 

 new Md_retailer(MyCC).start(); 

 new Vd_retailer(MyCC).start(); 

 } 

} 


class customer extends Thread { 

 private ComputerCenter cc; 

 private String name; 

 public customer(ComputerCenter cc,String name) { 

 this.cc = cc; 

 this.name = name; 

 } 


 public void run() { 

 while(true) { 

 //try {Thread.sleep(10);} catch (Exception e) {} 

 //顾客不断购买显卡和主板 

 cc.sellVd(name); cc.sellMd(name); 

 } 

 } 

} 

class Md_retailer extends Thread { 

 private ComputerCenter cc; 

 public Md_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockMd(); 

 } 

 } 

} 

class Vd_retailer extends Thread { 

 private ComputerCenter cc; 

 public Vd_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockVd(); 

 } 

 } 

} 

xmind (中级程序员) 2010-07-26 

恩,是有点儿,这样你看行不行,也就是顾客在买的时候,如果没有等待,买完后也不通知。电脑城在进货满之后不等待(或者sleep也行,让出cpu,现实中像是卖一段时间在进货),没进一个货就通知一声,只通知一个顾客。 

Java代码 

class ComputerCenter { 

 private static Object VIDEO = new Object(); 

 private static Object MAINB = new Object(); 

 private static Integer videoN = 10; 

 private static Integer MainbN = 10; 


 public void stockVd() { 

 synchronized(VIDEO) { 

 if(videoN >= 20) { 

 System.out.println("ComputerCenter: the VC storage is MAX"); 

 } else { 

 videoN++; 

 System.out.println("ComputerCenter: 厂商送来一块显卡。" + videoN); 

 VIDEO.notify();//----------------------------唤醒消费者消费 

 } 

 } 

 } 


 public void stockMd() { 

 synchronized(MAINB) { 

 if(MainbN >= 20) { 

 System.out.println("ComputerCenter: the MB storage is MAX"); 

 } else { 

 MainbN++; 

 System.out.println("ComputerCenter: 厂商送来一块主板。"+MainbN); 

 MAINB.notify();//-----------------------------唤醒消费者消费 

 } 

 } 

 } 


 public void sellVd(String name) { 

 synchronized(VIDEO) { 

 if(videoN <= 0) { 

 System.out.println("没有显卡了,等等,马上送来!!!!!!!!!"); 

 try {VIDEO.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块显卡。"+videoN); 

 videoN--; 

 } 

 } 


 public void sellMd(String name) { 

 synchronized(MAINB) { 

 if(MainbN <= 0) { 

 System.out.println("没有主板了,等等,马上送来!!!!!!!!!!"); 

 try {MAINB.wait();} catch (Exception e) {} 

 } 

 System.out.println(name + " : 买走一块主板。"+MainbN); 

 MainbN--; 

 } 

 } 


 public static void main(String[] args) { 

 ComputerCenter MyCC = new ComputerCenter(); 

 new customer(MyCC,"Jack").start(); 

 new customer(MyCC,"Tom").start(); 

 new Md_retailer(MyCC).start(); 

 new Vd_retailer(MyCC).start(); 

 } 

} 


class customer extends Thread { 

 private ComputerCenter cc; 

 private String name; 

 public customer(ComputerCenter cc,String name) { 

 this.cc = cc; 

 this.name = name; 

 } 


 public void run() { 

 while(true) { 

 //try {Thread.sleep(10);} catch (Exception e) {} 

 //顾客不断购买显卡和主板 

 cc.sellVd(name); cc.sellMd(name); 

 } 

 } 

} 

class Md_retailer extends Thread { 

 private ComputerCenter cc; 

 public Md_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockMd(); 

 } 

 } 

} 

class Vd_retailer extends Thread { 

 private ComputerCenter cc; 

 public Vd_retailer(ComputerCenter cc) { 

 this.cc = cc; 

 } 


 public void run() { 

 while(true) { 

 try {Thread.sleep(10);} catch (Exception e) {} 

 cc.stockVd(); 

 } 

 } 

}


xmind (中级程序员) 2010-07-26
lz基本的问题就是,厂商和客户等的不是同一把锁,所以要分别对待。然后就简单了。不过我的StockManager看着也不怎么对劲儿。