生产者与消费者

背景

生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
在这里插入图片描述举例说明:
1、你把信写好——相当于生产者制造数据
2、你把信放入邮筒——相当于生产者把数据放入缓冲区
3、邮递员把信从邮筒取出——相当于消费者把数据取出缓冲区
4、邮递员把信拿去邮局做相应的处理——相当于消费者处理数据

多线程使用生产者和消费者模式

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

实现方式

  1. wait()/notify()方法

现在希望实现一种数据的生产和取出的操作形式,即:有两个甚至更多的线程对象,这样的线程分为生产者线程和消费者线程。最理想的状态是生产者每生产完一条完整的数据之后,消费者久要取走这个数据,并且进行输出的打印。
将设置和取得数据的操作都交给同步方法来完成,但是此时会导致重复取数问题,如果要想解决重复问题,那么必须加入等待与唤醒的处理机制,由Object类提供有如下几种方法:
等待:public final void wait() throws InterruptedException;
唤醒第一个等待线程:public final void notify();
唤醒全部等待线程:public final void notifyAll();
notify()调用之后不会立即释放锁,而是当执行notify()的线程执行完成,即退出同步代码块或同步方法时,才会释放对象锁。
问题:请解释sleep()与wait()的区别?
sleep()是Thread类定义的方法,在休眠到一定时间之后将自己唤醒。
waitI()是Object类定义的方法,表示线程要等待执行,必须通过notify()、notifyAll()方法来进行唤醒。

producerAndConsumer.java
import java.util.LinkedList;

public class producerAndConsumer {

    private static final int MAX_COUNT=10;

    private LinkedList<Object> list = new LinkedList<>();

    /**
     * 生产产品-同步方法
     */
    public synchronized void produce(String producer){
        while(list.size()==MAX_COUNT){
            System.out.println("仓库已满,"+producer+":暂时不能执行生产任务");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            notifyAll();
        }

        //生产商品
        list.add(new Object());
        System.out.println(producer+"====>>生产的一个产品,【仓库储量】为:"+list.size());
        notifyAll();
    }

    /**
     * 消费者,消费产品
     */
    public synchronized void consumer(String consumer){
        while(list.size()==0){
            System.out.println("仓库空了,"+consumer+":暂时不能消费产品任务");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //消费商品
        list.remove();
        System.out.println(consumer+"====>>消费一个产品,【仓库储量】"+list.size());
        notifyAll();

    }

    public static void main(String[] args){
        producerAndConsumer storage = new producerAndConsumer();
        new Thread(new Producer("producer",storage)).start();
        new Thread(new Consumer("consumer",storage)).start();

    }

}

Producer.java
import java.util.concurrent.TimeUnit;

public class Producer implements Runnable {
    //生产者名称
    private  String name;
    //仓库
    private producerAndConsumer storage;

    public Producer(String name,producerAndConsumer storage){
        this.name=name;
        this.storage=storage;
    }
    @Override
    public void run() {

        while(true){
            storage.produce(name);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Consumer.java
import java.util.concurrent.TimeUnit;

public class Consumer implements Runnable {
    //消费者名称
    private String name;
    //仓库
    private producerAndConsumer storage;

    public Consumer(String name,producerAndConsumer storage){
        this.name=name;
        this.storage=storage;
    }

    @Override
    public void run() {
        storage.consumer(name);
//        try {
//            TimeUnit.MICROSECONDS.sleep(2500);
//
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }


    }

  1. await() / signal()方法
    在JDK5.0之后,Java提供了Lock与Condition机制。Condition接口的await()和signal()是用来做同步的两种方法,它们的功能基本上和Object的wait()、nofity()相同,或者说可以取代它们,但是它们和Lock机制是直接挂钩的。通过在Lock对象上调用newCondition()方法,将条件变量和一个锁对象进行绑定,进而控制并发程序访问竞争资源的安全。
package day1101;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Reentr
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值