多线程系列之生产者和消费者

来源:互联网 发布:flyme远程清除数据 编辑:程序博客网 时间:2024/06/18 14:47

在之前接触过PV操作的,应该对于生产者和消费者的情况有一个了解,这里学到多线程同步的时候,最恰当的一个例子。PV操作就不多做解释。

/** * 生产者和消费者 * @author bobo * */public class ProducerConsumer  {public static void main(String[] args) {SyncStack ss=new SyncStack();Producer p=new Producer(ss);Consumer c=new Consumer(ss);new Thread(p).start();new Thread(p).start();new Thread(c).start();new Thread(c).start();}}//产品-窝头class WoTou{int id;public WoTou(int id){this.id=id;}public String toString(){return "WOTou : "+id;}}//同步栈,产品盛放的容器 class SyncStack{int index=0;WoTou[] arrWT=new WoTou[6];//向容器中放产品时,其他线程不能使用,已经被锁定public synchronized void push(WoTou wt){while(index==arrWT.length){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();//通知消费者,可使用产品arrWT[index]=wt;index++;//放入产品}//向容器中拿产品时,其他线程不能使用,已经被锁定public synchronized  WoTou pop(){while(index==0){try {this.wait();//如果可拿资源为0,线程等待} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();//通知生产者,可以进行生产index--;return arrWT[index];//栈中有空位}}//生产者,向容器中放产品class Producer implements Runnable{SyncStack ss=null;Producer(SyncStack ss){this.ss=ss;}public void run(){for(int i=0;i<20;i++){WoTou wt= new WoTou(i);ss.push(wt);System.out.println("生产者生成:"+wt);try {Thread.sleep((int)(Math.random()*200));} catch (InterruptedException e) {e.printStackTrace();}}}}//消费者,从容器中取产品class Consumer implements Runnable{SyncStack ss=null;Consumer(SyncStack ss){this.ss=ss;}public void run(){for(int i=0;i<20;i++){WoTou wt=ss.pop();System.out.println("消费者消费:"+wt);try {Thread.sleep((int)(Math.random()*1000));} catch (InterruptedException e) {e.printStackTrace();}}}}


       有一个容器可以装产品,两边是生产者和消费者,可以是一个也可以是多个。他们为了保证生产者放一个,消费者拿一个,同时也不会出现,生产者还没有放,消费者就可以去拿了,那会使容器中的产品出现负数,这样显然是不对的。


       使用synchronized锁定代码块,让生产者向容器放东西的时候,消费者还不能拿到这个产品。

补充:

notify()/notifyAll()

通知,在生产者和消费者这个问题上,当生产者产生产品以后,可以通过信号量,通知消费者,它已经获得了资源。可以进行消费了。

防止大家都在等待,而造成线程阻塞。

wait()和sleep()区别

wait()是Object类中的方法,之后其他人可以使用

sleep()是Thread类的方法,之后其他人也不可以使用




原创粉丝点击