线程同步经典案例-生产者与消费者模型-Java

时间:2021-07-27 20:20:59

一、相关知识简介

      在生产者-消费者模型中,若只使用synchronized关键字实现对象锁,程序在运行中可能会出现以下两种情况:

  1. 若生产者的速度大于消费者,那么在消费者来不及取前一个数据之前,生产者又产生了新的数据,于是消费者很可能会跳过前一个数据。
  2. 若消费者的速度大于生产者,那么消费者可能多次取同一个数据。

          为了避免上述情况,必须使生产者向object对象中存储数据与消费者从object对象中取走数据同步起来。因此,在程序中可以采用信号量模型,同时通过调用对象的wait方法和notifyAll方法来实现同步。

           信号量模型的工作方式:线程在运行的过程中,可以主动停下来,等待某个信号量的通知,此时该线程就进入到该信号量的等待队列中,直到得到通知后,再继续运行。在Java语言中,Object对象的wait方法就是等待通知,notify或notifyAll方法就是发出通知,唤醒在该信号量的等待队列里面的相关线程。

二、生产者-消费者模型的案例 

package JavaPrograms;

/* * 该类的对象为共享资源 * 新增信号量available:当为true时,表示数据已经产生但还没被取走; * 当为false时,表示数据已经被取走但还没有存放新的数据。 */
class MyData2{
    private int content;
    private boolean available=false;
    public synchronized void put(int value){
        while(available==true){
            try{
                wait();
            }catch(InterruptedException e){

            }
        }
        this.content=value;
        available=true;
        notifyAll();
    }
    public synchronized int get(){
        while(available==false){
            try{
                wait();
            }catch(InterruptedException e){

            }
        }
        available=false;
        notifyAll();
        return this.content;
    }
}
/* * 生产者 */
class Producer2 extends Thread{
    private MyData2 data;
    public Producer2(MyData2 data){
        this.data=data;
    }
    public void run(){
        for(int i=1;i<=5;i++){
            this.data.put(i);
            System.out.println("生产者:生成物品,编号为:"+i);
            try{
                sleep((int)(Math.random()*100));
            }catch(InterruptedException e){

            }
        }
    }
}

/* * 消费者 */
class Consumer2 extends Thread{
    private MyData2 data;
    public Consumer2(MyData2 data){
        this.data=data;
    }
    public void run(){
        int value=0;
        for(int i=1;i<=5;i++){
            value=this.data.get();
            System.out.println("消费者:消费物品,编号为:"+value);
        }
    }
}
public class ProducerAndConsumer2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyData2 md=new MyData2();
        Producer2 p=new Producer2(md);
        Consumer2 c=new Consumer2(md);
        p.start();
        c.start();
    }
}

线程同步经典案例-生产者与消费者模型-Java