Java并发编程:线程间的协作wait()、notify()、notifyAll()和Condition

来源:互联网 发布:multisim12数据库下载 编辑:程序博客网 时间:2024/05/22 07:56

java并发编程协作有两种方式:1、利用Object对象下面的wait()、notify()或者notifyAll() 2、领用Condition的await()、singnal()或者singnalAll()

其中需要注意的是:

对于方式1、调用wait()、notify()或者notifyAll()  必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

对于方式2、await()、singnal()或者singnalAll()必须在lock()和unlock()方法中进行。

下面以常见的生成着和消费者模型为例,说明这两种方式的使用。我们以购物车为例,当购物车为空的时候,不允许从购物车中拿操作,当购物车满5个商品的时候为满,不允许再放入商品。本例仅仅为说明以上两个方式的使用,不具有说明实际意义

一、使用方式1

ShoppingCar.java

public class ShoppingCar {private Queue<String> queue = null;Lock lock = new ReentrantLock();public ShoppingCar(Queue<String> queue) {super();this.queue = queue;}public  void getGood(String i){synchronized (queue) {System.out.println("current queue size is "+queue.size()+" car"+i+" start get good");while(queue.isEmpty()){ try {System.out.println("car "+i+" get good stop");//当queue空的时候,等待,并让出对象锁queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}String g = queue.poll();System.out.println("car "+i+" get good "+ g +" suceed");queue.notifyAll();}}public  void addGood(String i,String g){synchronized (queue) {System.out.println("current queue size is "+queue.size()+" car"+i+" start add "+g);while(queue.size()>=5){try {System.out.println("car"+i+" add"+g+" stop");//当queue满的时候,等待,并让出对象锁queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("car "+i+" add "+g+" suceed");queue.add(g);queue.notifyAll();}}}
使用方式2

ShoppingCar2.java

public class ShoppingCar2 {private Queue<String> queue = null;Lock lock = new ReentrantLock();Condition empty =  lock.newCondition();Condition full = lock.newCondition();public ShoppingCar2(Queue<String> queue) {super();this.queue = queue;}public  void getGood(String i){lock.lock();try{System.out.println("current queue size is "+queue.size()+" car"+i+" start get good");while(queue.isEmpty()){try {System.out.println("car "+i+" get good stop");//当queue空的时候,等待,并让出对象锁empty.await();} catch (InterruptedException e) {e.printStackTrace();}}String g = queue.poll();System.out.println("car "+i+" get good "+ g +" sssuceed");full.signalAll();}finally{lock.unlock();}}public  void addGood(String i,String g){lock.lock();try{System.out.println("current queue size is "+queue.size()+" car"+i+" start add "+g);while(queue.size()>=5){try {System.out.println("car"+i+" add "+g+" stop");//当queue满的时候,等待,并让出对象锁full.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("car "+i+" add "+g+" suceed");queue.add(g);empty.signalAll();}finally{lock.unlock();}}}

调用:

public class Demo {public static void main(String[] args) {ShoppingCar2 car = new ShoppingCar2(new LinkedList<String>());<span style="white-space:pre"></span>ExecutorService addser = Executors.newCachedThreadPool();<span style="white-space:pre"></span>ExecutorService getser = Executors.newCachedThreadPool();<span style="white-space:pre"></span>for(int i=0;i<10;i++)<span style="white-space:pre"></span>addser.submit(new AddThread(i, car));<span style="white-space:pre"></span>for(int i=0;i<10;i++)<span style="white-space:pre"></span>getser.submit(new GetThread(i, car));<span style="white-space:pre"></span>addser.shutdown();<span style="white-space:pre"></span>getser.shutdown();}public  static class AddThread implements Runnable{ShoppingCar2 car = null;int id;public AddThread(int i,ShoppingCar2 car){this.car = car;this.id = i;}@Overridepublic void run() {while(true){car.addGood(String.valueOf(id),String.valueOf((int)(100*Math.random())));try {Thread.currentThread().sleep((int)(1000*Math.random())*10);} catch (InterruptedException e) {e.printStackTrace();}}}}public  static class GetThread implements Runnable{ShoppingCar2 car = null;int id;public GetThread(int i,ShoppingCar2 car){this.car = car;this.id = i;}@Overridepublic void run() {while(true){car.getGood(String.valueOf(id));try {Thread.currentThread().sleep((int)(1000*Math.random())*10);} catch (InterruptedException e) {e.printStackTrace();}}}}}
说明:购物车有两个操作,一个get商品、一个add商品、在Demo类中我们有一个AddThread类专门去add商品、一个GetThread类专门去get商品。main方法中,我们分别产出10个Get线程和10个Add线程去执行商品的add和get操作。

商品用一个随机生成的数字代替,get和add商品的时间也随机指定。执行结果如下:

<span style="color:#330000;">current queue size is 0 car0 start add 53car 0 add 53 suceedcurrent queue size is 1 car3 start add 58car 3 add 58 suceedcurrent queue size is 2 car4 start add 82car 4 add 82 suceedcurrent queue size is 3 car2 start add 33car 2 add 33 suceedcurrent queue size is 4 car6 start add 99car 6 add 99 suceedcurrent queue size is 5 car7 start add 53<span style="background-color: rgb(51, 204, 0);">car7 add 53 stop</span>current queue size is 5 car1 start add 45car1 add 45 stopcurrent queue size is 5 car8 start add 59car8 add 59 stopcurrent queue size is 5 car5 start add 58car5 add 58 stopcurrent queue size is 5 car9 start add 88car9 add 88 stopcurrent queue size is 5 car0 start get goodcar 0 get good 53 sssuceedcurrent queue size is 4 car3 start get goodcar 3 get good 58 sssuceedcurrent queue size is 3 car1 start get goodcar 1 get good 82 sssuceedcurrent queue size is 2 car2 start get goodcar 2 get good 33 sssuceedcurrent queue size is 1 car4 start get goodcar 4 get good 99 sssuceed<span style="background-color: rgb(0, 153, 0);">car 7 add 53 suceed</span>car 1 add 45 suceedcar 8 add 59 suceedcar 5 add 58 suceedcar 9 add 88 suceedcurrent queue size is 5 car5 start get goodcar 5 get good 53 sssuceedcurrent queue size is 4 car6 start get goodcar 6 get good 45 sssuceedcurrent queue size is 3 car8 start get goodcar 8 get good 59 sssuceedcurrent queue size is 2 car9 start get goodcar 9 get good 58 sssuceedcurrent queue size is 1 car7 start get goodcar 7 get good 88 sssuceedcurrent queue size is 0 car4 start add 88car 4 add 88 suceedcurrent queue size is 1 car9 start get goodcar 9 get good 88 sssuceedcurrent queue size is 0 car5 start add 1car 5 add 1 suceedcurrent queue size is 1 car9 start get goodcar 9 get good 1 sssuceedcurrent queue size is 0 car9 start get goodcar 9 get good stopcurrent queue size is 0 car1 start add 70car 1 add 70 suceed</span>

我们选取部分的结果分析,看标注的两个地方
<span style="color:#330000;"><span style="background-color: rgb(51, 204, 0);">car7 add 53 stop</span></span>

执行到这里时,购物车满了,没有添加到购物车

<span style="color:#330000;"><span style="background-color: rgb(0, 153, 0);">car 7 add 53 suceed</span></span>
到这里时候,由于有线程在get商品,此时购物车中商品小于5个了,可以添加商品了,就添加成功



0 0
原创粉丝点击