新手学JAVA,学到多线程,编了一个简单地电脑城进出货模拟系统。
代码有点长,主要部分如下所述:
有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。
主要代码如下,经过一定的简化以突出问题:
--------------------------厂家类---------------------------------------
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 显卡;
}}
-------------------------------------顾客类-------------------------------------------
public class customer implements Runnable
{
public void run()
{
while(true)
{
buyVC("ATI");
//顾客不断购买显卡和主板
buyMB("MSI");
}
}}
-----------------------------电脑城类-----------------------------------------
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.如果两家厂商正在等待消费者购买商品,此时显卡厂商被唤醒后,可能立刻唤醒主板厂商生产主板,令到商品数量超出仓库上限。我想,有没有什么办法,可以指定唤醒某个线程?如果可以,那问题就容易解决了。
代码有点长,主要部分如下所述:
有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。
主要代码如下,经过一定的简化以突出问题:
--------------------------厂家类---------------------------------------
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 显卡;
}}
-------------------------------------顾客类-------------------------------------------
public class customer implements Runnable
{
public void run()
{
while(true)
{
buyVC("ATI");
//顾客不断购买显卡和主板
buyMB("MSI");
}
}}
-----------------------------电脑城类-----------------------------------------
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.如果两家厂商正在等待消费者购买商品,此时显卡厂商被唤醒后,可能立刻唤醒主板厂商生产主板,令到商品数量超出仓库上限。我想,有没有什么办法,可以指定唤醒某个线程?如果可以,那问题就容易解决了。
解决方案 »
- 发个行转列的代码,顺便和大家交流下平时大家都怎么处理行转列
- Java发送邮件附件不成功,高手请留步!!本人高分答谢!!
- 请问:GroupBox 控件在 Java 里叫什么?
- 在URL中想访问getCodeBase()的上级目录,help
- 请教高手这个存储过程怎么写?可能包含一点算法在里面,解决后加分
- 程序退出的时候如何记下日志!?
- 欣赏一下
- 我在使用DefaultTableModel的时候遇到了问题,您能提供我一个成功使用DefaultTableModel的例子吗?
- ++++++++JDK不同版本存在的问题+++++++++
- 检索结果条数很多,会影响速度吗?
- 请教Dynamic ClassLoading&Reflection问题,有代码,拜求高手!
- 跪求:java.net.SocketException: 在一个非套接字上尝试了一个操作
满足条件继续,不满足则继续等待
我直接说一说了,
你已经说到点子上了
"没有什么办法,可以指定唤醒某个线程?如果可以,那问题就容易解决了。"实际上达到这一点很简单,每个线程之所以能被唤醒是因为它wait的那个对象被notify了,所以你需要的是多少被wait的对换。你之前的代码的问题在于,所有的人,厂家也好,消费者也好,都是在等一个Object,也就是ComputerCenter实例本身,当这个对象notify其他线程,它只能说明“我被改变了”,但不能表达“我进货了”, “我出货了”这些不同的改变。对每一种东西,显卡,你需要的是两个notify的channel(两个对象)
1. 厂家供一个货 notify一个customer (如果有customer在等)
2. customer买一个货,notify厂家供家 (如果说有厂家在等)主板同样处理。示意代码:
ComputerCenter {Object lockObjectVideoFull = new Object();
Object lockObjectVideoEmpty = new Object();sellVideoCard(){ if (is already empty) {
lockObjectVideoEmpty.wait();
}else {
pop out a vidoe card
lockObjectVideoFull.notify();
}}stockVideoCard() {
if (is already full) {
lockObjectVideoFull.wait();
} else {
push new card in
lockObjectEmpty.wait();
}
}}
实际上,你的design比你想像的复杂,因为从你的代码看来,你还想支持不同品牌的显卡和主板 stockCard("ATI")
stockCard("Nivida")这样因为每个品牌的显卡都可能独立出现缺货和货满的情况,实质上你要对每个品牌保留
两个lock对象
Map<String, Object[2]> vidoeCardLock;videoCardLock.get("ATI")[0] - emptylock
videoCardLock.get("ATI")[1] - fulllock
另外你的代码貌似结构上得再修正修正
thanks,非常感谢。
另外:另外你的代码貌似结构上得再修正修正--本人初学编程一个月不到,愿闻其详
你先把程序弄work吧,然后我们再谈这些形而上学的东西不迟
没有,就是程序能run就可以了。你们刚学Java很认真啊。
其中进主板,卖主板是靠主板库存联系起来的。进显卡,卖显卡是靠显卡库存联系起来的。这样我们只考虑主板,因为主板和显卡是同一个问题。
这里我忽略了厂商是因为厂商的生产动作没有任何约束,而供货/进货这个动作在电脑城这里已经约束了。首先说进货,如果存货达到上限它就应该等待,等待什么呢?等待库存不等于上限。你可以调用 saved.wait();
相应的,在卖货的方法里就要调用saved.notify()。来唤醒等待中的动作。出货呢就是库存为0是wait()。 在进货的代码里notify();最后说一点我的心得,wait()方法不应该简单的理解成让当前线程停止了。调用wait都是调用锁的wait()表示当前线程在等待这个锁,别人notify的时候,这个线程就继续执行了