java 线程2 生产者消费者模型(wait和notify方法的用法和底层原理)

生产者消费者模型

生产者 - 消费者模型( Producer-consumer problem) 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见

  • 生产者: 生产商品放入缓冲区
  • 缓冲区:存放商品的地方,容量有限
  • 消费者: 消费缓冲区的商品

java 实现生产者消费者模型

在这里插入图片描述

wait notify notifyAll 方法

调用 wait() 和notify()的对象必须是 同一个 ,因为会被放入 同一个等待队列里面,比如在生产者1 线程里面调用Warehouse.wait()方法, 生产者1线程就被放入 Warehouse的等待队列当中,直到Warehouse调用 notify()或者notifyAll()方法,就是是让线程得到obj锁

  • wait( ),notify( ),notifyAll( )都属于Object基础类,也就是每个对象都有wait( ),notify( ),notifyAll( ) 的功能
  • 当需要调用以上的方法的时候,需要对竞争资源进行加锁

也可以用condition接口实现

wait() 看起来是1个函数,其实是3个

(JDK11.0)Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
导致当前线程等待(waiting),直到被唤醒(notify 或notifyAll )或者打断,或者一段时间过去(time-waiting)

wait()

导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法

wait(long timeout)

Causes the current thread to wait until either another thread invokes the notify( ) method or the notifyAll( ) method for this object, or a specified amount of time has elapsed.
导致当前的线程等待,直到其他线程调用此对象的notify() 方法或 notifyAll() 方法,或者指定的时间过完。

void wait(long timeout, int nanos)

Causes the current thread to wait until another thread invokes the notify( ) method or the notifyAll( ) method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法,或者其他线程打断了当前线程,或者指定的时间过完。

  • wait 必须加锁(lock)或者放入同步代码(synchronized)块里面
  • 当运行到wait()方法,会立刻释放竞争对象的执行权

notify()

  • Wakes up a single thread that is waiting on this object’s monitor.
    唤醒在此对象监视器上等待的单个线程(也就是最先进入等待队列的线程)
  • 只有在同步代码块执行完毕之后,才会唤醒线程

notifyAll()

-Wakes up all threads that are waiting on this object’s monitor.
唤醒在此对象监视器上等待的所有线程(也就是在等待队列里的所有线程)

  • 只有在同步代码块执行完毕之后,才会唤醒线程

java 代码

** 生产者Producer**

public class Producer implements Runnable {

    Lock lock = new ReentrantLock();//锁
    ArrayList<String> warehouse;
    int goods = 0;

    Producer(ArrayList<String> warehouse) {
        this.warehouse = warehouse;
    }
    
    @Override
    public void run() {
        
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (warehouse) {

                while (warehouse.size() >= 10) {
                    System.out.println("仓库容量" + warehouse.size() + " 容量满了,生产者停止消费");
                    System.out.println();
                    try {
                        warehouse.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }//加锁的时候,自动释放warehouse 的执行权
                }
                
                String a = String.valueOf(goods);
                warehouse.add(a);
                String thread_name = Thread.currentThread().getName();
                System.out.println(thread_name + "  生产了 " + goods);
                goods++;
                warehouse.notify(); // 唤起消费者

            }
        }
    }
}

** 消费者Costomer**

public class Customer implements Runnable{

    Lock lock  = new ReentrantLock();//锁
    ArrayList<String> warehouse;
    int goods=0;
    Customer(ArrayList<String> warehouse){
        this.warehouse =warehouse;
    }
    @Override
    public void run() {

        while (true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (warehouse){
                while (warehouse.size() == 0){
                    System.out.println("没有货物了 消费者停止消费");
                    System.out.println();
                    try {
                        warehouse.wait(); //加入仓库的等待队列
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }// 没有货物,直接挂起
                
                String good_name =warehouse.get(0);
                String thread_name =Thread.currentThread().getName();
                warehouse.remove(0);
                System.out.println(thread_name+"  消费了 "+good_name);
                //消费第一个货物
                warehouse.notify();//唤醒生产者
            }
        }
    }
}

** 主函数: 缓冲区Warehouse 是一个arrylist 默认容量是10 **

public class Main {
    public static void main(String[] args) {
        ArrayList<String> warehouse =new ArrayList<>(10);//容量是10

        Customer customer =new Customer(warehouse);
        Producer producer =new Producer(warehouse);

        Thread thread_P1 = new Thread(producer);
        thread_P1.setName("生产者1");
        Thread thread_P2 = new Thread(producer);
        thread_P2.setName("生产者2");

        Thread thread_C1 = new Thread(customer);
        thread_C1.setName("消费者1");
        Thread thread_C2 = new Thread(customer);
        thread_C2.setName("消费者2");

        thread_P1.start();
        thread_C1.start();
        thread_P2.start();
        thread_C2.start();
    }
}

运行结果(看来花钱总比赚钱容易呀)
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值