Java生产与消费者模型---等待唤醒机制

生产者与消费者模型简介

生产者和消费者彼此之间不直接沟通,而通过阻塞队列来进行通讯,当生产者生产的商品不足时,生产者开始生产,消费者进行阻塞,当生产者生产充足的商品后,唤醒消费者,进行出售......所以生产者生产完数据之后不会等待消费者处理,直接唤醒阻塞队列中的所有线程,同时自身阻塞,消费者在消费完成后,同时唤醒阻塞队列中的所有线程,自身进行阻塞.......阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的能力

wait()方法

  • 方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法是用来将当前线程置入“预执行队列”中,并且wait()所在的代码处停止执行,知道接到通知或被中断为止
  • wait()只能在同步方法或同步代码块中调用,如果调用wait()时,没有适当的锁会抛出异常
  • wait()方法执行后,当前线程释放锁,线程与其它线程竞争重新获取锁

notify()方法

  • 方法notify()作用是使停止的线程继续运行
  • 方法notify()也要在同步方法或同步代码块中调用,该方法是用来通知那些可能等待该对象的对象锁的其他线程,对其发出通知notify,并使它们重新获取该对象的对象锁,如果有多个线程等待,线程规划器随机挑选一个呈wait状态的线程
  • 在notify()之后,当前对象不会马上释放对象锁,要等到执行notify()方法的线程将程序执行完,也就使退出同步代码块之后才会释放对象锁

notifyAll()方法

  • 同notify()方法,当时他可一次性唤醒阻塞队列所有的线程

注意:每个锁对象有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒,得到notify通知后只是从等待队列移出来。在移出来的时候,有可能不直接进入就绪队列直接拿到对象锁,但大多情况下是直接进入就绪队列

单生产单消费模型

商品类

package com.lin;

import org.omg.PortableServer.THREAD_POLICY_ID;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:06
 */
public class Goods {
    private String goodsName;
    private int count;

    public Goods() {

    }

    public synchronized void set(String goodsName) throws InterruptedException {
        //当生产者生产产品数量超过5个,则等待阻塞,释放对象锁,由消费者竞争锁
        if (this.count>5) {
            System.out.println("还有商品库存,等待消费者消费");
            wait();
        }
        this.goodsName=goodsName;
        this.count++;
        Thread.sleep(1000);
        System.out.println("生产"+toString());
        //唤醒消费者线程,此时已有商品
        notify();
    }

    public synchronized void get() throws InterruptedException {
        当没有商品买了,自身阻塞等待,释放对象锁,等待生产者生产出商品在竞争锁继续运行
        if (this.count==0) {
            System.out.println("商品已卖完,等待生产者生产");
            wait();
        }
        this.count=this.count-1;
        Thread.sleep(1000);
        System.out.println("消费"+toString());
        //唤醒生产者线程,此时可能会即将没有商品
        notify();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}

生产者

package com.lin;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:11
 */
public class Producer implements Runnable{
    private Goods goods;

    public Producer(Goods goods) {
        super();
        this.goods = goods;
    }

    @Override
    public void run() {
            try {
                this.goods.set("小黑瓶");
            } catch (InterruptedException e) {
                e.printStackTrace();
        }
    }
}

消费者

package com.lin;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:11
 */
public class Consumer implements Runnable{
    private Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
            try {
                this.goods.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }
}

测试

package com.lin;

import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:17
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Goods goods=new Goods();
        Thread thread1=new Thread(new Producer(goods),"生产者");
        Thread thread2=new Thread(new Consumer(goods),"消费者");
        thread1.start();
        thread2.start();
    }
}

程序运行结果

生产者生产Goods{goodsName='小黑瓶', count=1}
生产者生产Goods{goodsName='小黑瓶', count=2}
生产者生产Goods{goodsName='小黑瓶', count=3}
生产者生产Goods{goodsName='小黑瓶', count=4}
生产者生产Goods{goodsName='小黑瓶', count=5}
生产者生产Goods{goodsName='小黑瓶', count=6}
消费者消费Goods{goodsName='小黑瓶', count=5}
生产者生产Goods{goodsName='小黑瓶', count=6}
还有商品库存,等待消费者消费
消费者消费Goods{goodsName='小黑瓶', count=5}
消费者消费Goods{goodsName='小黑瓶', count=4}
消费者消费Goods{goodsName='小黑瓶', count=3}
消费者消费Goods{goodsName='小黑瓶', count=2}
生产者生产Goods{goodsName='小黑瓶', count=3}
消费者消费Goods{goodsName='小黑瓶', count=2}
消费者消费Goods{goodsName='小黑瓶', count=1}
消费者消费Goods{goodsName='小黑瓶', count=0}
商品已卖完,等待生产者生产

多生产者多消费者模型

商品类

package com.lin;


/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:06
 */
public class Goods {
    private String goodsName;
    private int count;

    public Goods() {

    }

    public synchronized void set(String goodsName) throws InterruptedException {
        //若此时商品已充足,不需生产,则循环阻塞所有生产者线程
        while (this.count>5) {
            System.out.println("还有商品库存,等待消费者消费");
            wait();
        }
        this.goodsName=goodsName;
        this.count++;
        Thread.sleep(1000);
        System.out.print(Thread.currentThread().getName());
        System.out.println("生产"+toString());
        //已生产商品,唤醒所有线程
        notifyAll();
    }

    public synchronized void get() throws InterruptedException {
        //已无商品可买,需要生产者生产,循环阻塞消费者线程
        while (this.count==0) {
            System.out.println("商品已卖完,等待生产者生产");
            wait();
        }
        this.count=this.count-1;
        Thread.sleep(1000);
        System.out.print(Thread.currentThread().getName());
        System.out.println("消费"+toString());
        //可能商品数量不足,唤醒所有线程
        notifyAll();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}

生产者

package com.lin;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:11
 */
public class Producer implements Runnable{
    private Goods goods;

    public Producer(Goods goods) {
        super();
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true) {
            try {
                this.goods.set("小黑瓶");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者

package com.lin;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:11
 */
public class Consumer implements Runnable{
    private Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while (true) {
            try {
                this.goods.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

测试类

package com.lin;

import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Author:  llf
 * Created in 2019/8/5 14:17
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Goods goods=new Goods();
        List threadList=new ArrayList();
        for (int i = 0; i <10 ; i++) {
            Thread thread1=new Thread(new Producer(goods),"生产者"+i);
            threadList.add(thread1);
        }
        for (int i = 0; i < 6; i++) {
            Thread thread2=new Thread(new Consumer(goods),"消费者"+i);
            threadList.add(thread2);
        }
        for (Thread thread:threadList) {
            thread.start();
        }
    }
}

运行结果

生产者0生产Goods{goodsName='小黑瓶', count=1}
生产者0生产Goods{goodsName='小黑瓶', count=2}
生产者0生产Goods{goodsName='小黑瓶', count=3}
生产者0生产Goods{goodsName='小黑瓶', count=4}
生产者0生产Goods{goodsName='小黑瓶', count=5}
生产者0生产Goods{goodsName='小黑瓶', count=6}
消费者5消费Goods{goodsName='小黑瓶', count=5}
消费者3消费Goods{goodsName='小黑瓶', count=4}
消费者3消费Goods{goodsName='小黑瓶', count=3}
消费者3消费Goods{goodsName='小黑瓶', count=2}
消费者3消费Goods{goodsName='小黑瓶', count=1}
消费者4消费Goods{goodsName='小黑瓶', count=0}
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
生产者9生产Goods{goodsName='小黑瓶', count=1}

 

你可能感兴趣的:(Java生产与消费者模型---等待唤醒机制)