生产消费模型
一 什么是生产消费模型
当多个线程共享一个数据的时候,处于线程安全的考虑我们只让这些线程一次只能一个线程使用和更改数据(保证数据的安全);生产消费模型使用场景在于当仓库满的时候,让生产者不在生产,当仓库是空的时候,让消费者不在消费(这个时候我们的线程是拿到了锁也就是拿到了执行权,所以wait方法能够释放同一个贡献数据限制的锁),释放锁以后会有一个线程拿到锁,继续对仓库的数据进行改变,当改变了数据以后,需要唤醒共用同一个锁对象的线程,它们之间争抢锁,进而争抢执行权,进而对数据进行更改。
二 wait()方法和notify ()方法
1.wait()方法:让当前线程(持有锁的线程)处于等待(阻塞)的状态,并且释放它持有的锁。该线程将处于阻塞状态,直到其它线程调用notify()或者notifyAll()方法唤醒,线程进入就绪状态。
2.notify():唤醒持有锁上的其中一个线程。让那个线程从等待状态变成就绪状态
相关代码实现生产消费模型demo
代码实现`在这里插入代码片
仓库的代码:
package com.lk.PC0414;
import java.util.LinkedList;
import java.util.List;
import org.bridj.objc.ObjCObject;
public class Storage {
private final int Max_num=20;
private LinkedList<Object> list=new LinkedList<>();
public void produce()
{
synchronized (list) {
while(list.size()+1>Max_num)
{
System.out.println(Thread.currentThread().getName()+" 仓库已满不能在添加数据:");
try {
//wait方法的使用是,list这个对象在那个线程被使用那样的话,那个线程就会睡眠下来
//wait方法会释放线程占有的锁
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
list.add(new Object());
System.out.println(Thread.currentThread().getName()+ " 生产者生产了一个数据"+"现在的库存是"+list.size());
//唤醒共享list数据的所有的相关的线程
//notifyAll不会释放占有的锁
list.notifyAll();
}
}
public void consume()
{
synchronized(list) //这个的目的是为了只让一个线程动用共享数据当中的一个数据
{
while(list.size()==0)
{
System.out.println(Thread.currentThread().getName()+" 仓库已空不能在消费数据:");
//因为不能在消费了所以必须要让消费仓库中数据的线程暂时停下来
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//移除列表的最后一个数据
list.remove();
System.out.println(Thread.currentThread().getName()+ " 消费者消费了一个数据"+" 现在的库存是"+list.size());
list.notifyAll();//唤醒所有的线程来争取执行权
}
}
}
生产者的代码:
package com.lk.PC0414;
public class Producer implements Runnable{
public Storage storage;
public Producer()
{
}
public Producer(Storage storage)
{
this.storage=storage;
}
//run方法结束则线程结束
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(600);
//方法作用是往storage类当中的list仓库当中添加了一个实例
storage.produce();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
消费者的代码:
package com.lk.PC0414;
public class Consumer implements Runnable{
public Storage storage;
public Consumer()
{
}
public Consumer(Storage storage)
{
this.storage=storage;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(1000);
//共用的数据跟锁全都是storage里面的那个列表
storage.consume();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试代码:
package com.lk.PC0414;
//生产消费模型主要是解决一下线程安全问题和相关的数据不够了仓库暂停消费,仓库满了数据停止增长,让线程不断周期运转
//wait 和notify是实现线程之间通信的一个方法
public class Test {
public static void main(String[] args) {
Storage storage =new Storage();
//四个生产者,两个消费者
Producer pr1=new Producer(storage);
Producer pr2=new Producer(storage);
Producer pr3 =new Producer(storage);
Producer pr4=new Producer(storage);
Consumer co1=new Consumer(storage);
Consumer co2=new Consumer(storage);
new Thread(pr1).start();
new Thread(pr2).start();
new Thread(pr3).start();
new Thread(pr4).start();
new Thread(co1).start();
new Thread(co2).start();
}
}
运行的相关实例