JAVA技巧(Java线程间的通信) |
|
www.nanhushi.com 佚名 不详 |
线程间的通信(生产者-消费者模式) 有如下情形,线程A向盘子里放桔子(盘子很小,只能容得下一个桔子),放完桔子后,如果其它线程没有来拿桔子,则A下次再放桔子时,留在盘子里的上次那个桔子就被覆盖掉了(现实并非这样),但我们并不希望这个可口的桔子就这样被第二个桔子覆盖掉。我们的理想情况是:线程A每次在盘子里放完一个桔子后,马上通知其它线程来取这个桔子,这时,线程A就暂停放桔子在盘子里,其它线程取走桔子之后,马上通知A桔子已经被取走,这时,A继续放下一个桔子,并通知其它线程来取,这样反复下去(为了不让产生者永久的放,消费者永久地取,可限定生产者一共要放100次桔子)……于是,放一个就取走一个,所有桔子都被成功取走。 在上述案例子中,线程A与线程B之间是生产者与消费者的关系,线程A生产桔子,把桔子在盘子里,线程B从盘子里拿走桔子,享受美味。而且,为了达到生产一个,拿走一个,这样的一对一的过程,线程A必须告诉线程B:桔子已经放好了,来拿吧,你拿走了,我再放下一个。当线程B拿走后,必须告诉线程A:我把桔子拿走了,你快放下一个吧。线程A和B互相告诉对方的动作,就是线程间的通信。 取放桔子的整个过程,涉及到了四个对象,分别是生产者(线程A),消费者(线程B),消费的商品(桔子),商店(盘子)。因此,可以把上述过程看作是生产者和消费者在商店里交易桔子。下图描绘了上述整个过程:

下面的代码实现了本案例: class MyTest1{ public static void main(String[] args){ Panel pan = new Panel(); Consumer c = new Consumer(pan); Producer p = new Producer(pan, c); c.setDaemon(true);/*将消费者设为守护线程,也就是说,当生产者不再生产时,消费者立即主动不再消费*/ p.start(); c.start(); } }
class Producer extends Thread{ Panel pan = null; Consumer c = null; public Producer(Panel pan, Consumer c){ this.pan = pan; this.c = c; } public void run(){ synchronized(c){ int count = 0; //Examda提示: 生产者一共要生产100个桔子 while(count++ < 100){ if(!pan.isBlank){ try{c.wait();}catch(Exception ex){ex.printStackTrace();} } int orgWeight = (int)(Math.random() * 100); Orange org = new Orange(orgWeight, "red"); pan.putOrange(org); c.notify(); } } } } class Consumer extends Thread{ Panel pan; public Consumer(Panel pan){ this.pan = pan; } public void run(){ synchronized(this){ while(true){ if(pan.isBlank){ try{wait();}catch(Exception ex){ex.printStackTrace();} } pan.getOrange(); notify(); } } } } class Orange{ int weight; String color; public Orange(int weight, String color){ this.weight = weight; this.color = color; } public String toString(){ return "Orange, weight = " + weight + ", color = " + color; } } class Panel{ public boolean isBlank = true; private Orange org; public void putOrange(Orange org){ this.org = org; isBlank = false; System.out.println("I put: " + org.toString()); } public Orange getOrange(){ System.out.println("I get: " + org.toString()); isBlank = true; return org; } } www.Examda.CoM
|
|
|
文章录入:杜斌 责任编辑:杜斌 |
|
上一篇文章: 为同类Portlet设置不同的ICON 下一篇文章: observer模拟监听器的实现 |
【字体:小 大】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 |
|
|