java--生产与消费者模型

目录

1 几个重要的方法

1.1 wait()方法

1.2 notify()方法

1.3 notifyAll()方法

2 单线程生产与消费者模型

2.1 改进前的模型

2.1 改进后的模型

3 多线程生产与消费者模型

3.1 有限个生产者和消费者

3.2 多个生产者和消费者


1 几个重要的方法

1.1 wait()方法

使线程停止运行,会释放对象锁。

a. 该方法的三个特点

  • wait()方法会使当前线程调用该方法后进行等待,并且将该线程置入锁对象的等待队列中,直到接到通知或中断为止
  • wait()方法只能在同步方法或同步代码块中调用,如果调用wait()方法时没有适当的锁,会抛出异常
  • wait()方法执行后,当前线程释放锁,其他线程可以竞争该锁

b. wait()之后的线程继续执行的方法:

  • 调用该对象的notify()方法唤醒线程
  • 线程等待时调用interrupt()进行中断

1.2 notify()方法

唤醒线程

该方法的特点

  •  notify( )方法也必须在同步方法或同步代码块中调用,用来唤醒等待在该对象上的线程,如果有多个线程等待,则任意挑选一个线程唤醒。
  •  notify( )方法执行后,唤醒线程不会立即释放对象锁,要等待唤醒线程全部执行完毕后才释放对象锁

1.3 notifyAll()方法

唤醒所有在该对象上等待的线程

2 单线程生产与消费者模型

2.1 改进前的模型

class Goods{
    private String goodsName;
    private int count;
    //生产商品方法
    public synchronized void set(String goodsName){
        this.goodsName = goodsName;
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产"+goodsName+toString());
    }
    //消费商品方法
    public synchronized void get(){
        this.goodsName = goodsName;
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费"+goodsName+toString());
    }
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}
class Consume implements Runnable{
    private Goods goods;
    public Consume(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.get();
    }
}
class Produce implements Runnable{
    private Goods goods;
    public Produce(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.set("爱豆");
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods();
        Thread consumeThread = new Thread(new Consume(goods));
        Thread produceThread = new Thread(new Produce(goods));
        produceThread.start();
        Thread.sleep(2000);
        consumeThread.start();
    }
}

运行结果:

但如果将代码改成先调用消费者线程,如下代码,则会出现消费为负数的情形:

public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods();
        Thread consumeThread = new Thread(new Consume(goods));
        Thread produceThread = new Thread(new Produce(goods));
        consumeThread.start();
        Thread.sleep(2000);
        produceThread.start();
    }
}

运行结果:

2.1 改进后的模型

基于上述先消费后生产的情形, 我们可以做如下的改进, 引入wait()和notify():

class Goods{
    private String goodsName;
    private int count;
    //生产商品方法
    public synchronized void set(String goodsName){
        if(count>0){
            System.out.println("商品还有库存,等会再忙...");
            try {
                //等待消费者消费
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodsName = goodsName;
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产"+goodsName+toString());
        //唤醒等待消费的线程
        notify();
    }
    //消费商品方法
    public synchronized void get(){
        if(count==0){
            System.out.println("商品买完了,等一哈~,马上就到了~~");
            try {
                //等待生产商品
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodsName = goodsName;
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费"+goodsName+toString());
        //唤醒生产者进行生产
        notify();
    }
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}
class Consume implements Runnable{
    private Goods goods;
    public Consume(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.get();
    }
}
class Produce implements Runnable{
    private Goods goods;
    public Produce(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.set("爱豆");
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods();
        Thread consumeThread = new Thread(new Consume(goods),"消费者");
        Thread produceThread = new Thread(new Produce(goods),"生产者");
        consumeThread.start();
        Thread.sleep(2000);
        produceThread.start();
    }
}

运行结果:

这时就不会出现负消费的情形了~

3 多线程生产与消费者模型

3.1 有限个生产者和消费者

class Goods{
    private String goodsName;
    private int count;
    //生产商品方法
    public synchronized void set(String goodsName){
        while (count>0){
            System.out.println("商品还有库存,等会再忙...");
            try {
                //等待消费者消费
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodsName = goodsName;
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产"+goodsName+toString());
        //唤醒等待消费的线程
        notifyAll();
    }
    //消费商品方法
    public synchronized void get(){
        //不断判断执行  注!!!次数不能用if,if判断一次就结束了,程序运行会出现负消费~
        while (count==0){
            System.out.println("商品买完了,等一哈~,马上就到了~~");
            try {
                //等待生产商品
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodsName = goodsName;
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费"+goodsName+toString());
        //唤醒生产者进行生产
        notifyAll();
    }
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}
class Consume implements Runnable{
    private Goods goods;
    public Consume(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.get();
    }
}
class Produce implements Runnable{
    private Goods goods;
    public Produce(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        goods.set("爱豆");
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods();
        //存储多个生产、消费者线程
        List<Thread> list = new ArrayList<>();
        //10个消费者线程
        for(int i = 0;i < 10; i++){
            Thread thread = new Thread(new Consume(goods),"消费者"+i);
            list.add(thread);
        }
        //5个生产者模型
        for(int i = 0;i < 5; i++){
            Thread thread = new Thread(new Produce(goods),"生产者"+i);
            list.add(thread);
        }
        for (Thread thread:list){
            thread.start();
        }
    }
}

运行结果:

3.2 多个生产者和消费者

class Goods{
    private String goodsName;
    private int count;
    public int getCount() {
        return count;
    }
    //生产商品方法
    public synchronized void set(String goodsName){
        /*while (count>0){
            System.out.println("商品还有库存,等会再忙...");
            try {
                //等待消费者消费
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }*/
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.goodsName = goodsName;
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产"+goodsName+toString());
        //唤醒等待消费的线程
        notifyAll();
    }
    //消费商品方法
    public synchronized void get(){
        //不断判断执行  注!!!次数不能用if,if判断一次就结束了,程序运行会出现负消费~
        while (count==0){
            System.out.println("商品买完了,等一哈~,马上就到了~~");
            try {
                //等待生产商品
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.goodsName = goodsName;
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费"+goodsName+toString());
        //唤醒生产者进行生产
        notifyAll();
    }
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }
}
class Consume implements Runnable{
    private Goods goods;
    public Consume(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        while (true){
            goods.get();
        }
    }
}
class Produce implements Runnable{
    private Goods goods;
    public Produce(Goods goods) {
        this.goods = goods;
    }
    public void run() {
        //限制生产量
        while (this.goods.getCount()<10){
            goods.set("爱豆");
        }
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods();
        //存储多个生产、消费者线程
        List<Thread> list = new ArrayList<>();
        //10个消费者线程
        for(int i = 0;i < 10; i++){
            Thread thread = new Thread(new Consume(goods),"消费者"+i);
            list.add(thread);
        }
        //5个生产者模型
        for(int i = 0;i < 5; i++){
            Thread thread = new Thread(new Produce(goods),"生产者"+i);
            list.add(thread);
        }
        for (Thread thread:list){
            thread.start();
        }
    }
}

运行结果是生产者和消费者迭代进行...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值