多线程模型-生产者消费者模型和仓储模型

本文详细介绍了生产者消费者模型的实现,包括单生产者单消费者、多生产者多消费者两种情况,并通过仓储模型进行示例。在模型中,使用对象监视器协调生产者和消费者的同步,避免数据竞争。同时,讨论了wait()和notify()方法在多线程协作中的作用以及对象监视器的选择。
摘要由CSDN通过智能技术生成

多线程模型

生产者消费者模型要用到对象监视器,先看扩展。

生产者消费者模型

套用生产者消费者模型的情况:多线程操作同一个资源,并且多个线程的功能不一样,就用生产者消费者模型。

生产者消费者模型理解图:
在这里插入图片描述

1、一个生产者一个消费者

//需求:生产一个消费一个		
public class Phone {
    private String brand;
    private double price;
    private boolean isStore;//是否有库存
    public Phone() {}
    public Phone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
//TODO补全get set toString。。。。
}
public class Consumer extends Thread{
    private Phone phone;
    public Consumer(Phone phone) {
        this.phone = phone;
    }
    @Override
    public void run() {
        while (true){
            synchronized(phone){
                if (!phone.isStore()){//没库存
                    try {
                        phone.wait();//对象监视器,等待,进入阻塞,wait来自Object 会自动释放锁资源
                        //sleep是Thread的,不会释放锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(phone);
                phone.setStore(false);
                phone.notify();//唤醒对象监视器中记录的第一个线程
            }
        }
    }
}
public class Producer extends Thread{
    private Phone phone;
    public Producer(Phone phone) {
        this.phone = phone;
    }
    @Override
    public void run() {
        boolean flag = true;
        while(true){
            synchronized(phone){
                if (phone.isStore()){//有库存
                    try {
                        phone.wait();//
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (flag){
                    phone.setBrand("华为");
                    phone.setPrice(3999);
                }else {
                    phone.setBrand("小米");
                    phone.setPrice(1999);
                }
                flag = !flag;
                phone.setStore(true);
                phone.notify();//
            }
        }
    }
}
public static void main(String[] args) {
    Phone phone = new Phone();
    Producer p = new Producer(phone);
    Consumer c = new Consumer(phone);
    p.start();
    c.start();
}

2、多个生产者多个消费者

//需求:生产一个消费一个	
public class Phone{}//和上面一样
public class Consumer extends Thread{
    private Phone phone;
//TODO构造方法。。。
    @Override
    public void run() {
        while (true){
            synchronized(phone){
                while (!phone.isStore()){//没库存//----变
                    try {
                        phone.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(phone);
                phone.setStore(false);
                phone.notifyAll();//----变
            }
        }
    }
}
//如果这两个地方没变,会出现各种奇奇怪怪的脏数据,可以自己考虑下为什么会出现这些鬼东西。
//注:wait()等待唤醒后是接着wait往下执行的
public class Producer extends Thread{}//变化的地方和Consumer一样
public static void main(String[] args) {
    Phone phone = new Phone();
    Producer p1 = new Producer(phone);
    Producer p2 = new Producer(phone);
    Consumer c1 = new Consumer(phone);
    Consumer c2 = new Consumer(phone);
    p1.start();
    p2.start();
    c1.start();
    c2.start();
}

仓储模型

生产者消费者模型的一种

1.一个生产者一个消费者

public class Cake {
    private String brand;
	private String dataTime;
    //TODO 有参无参构造 get set toString。。。
}
public class Store {
	//蛋糕容器
	private LinkedList<Cake> list = new LinkedList<>();
	//最大容量
	private int maxCapacity = 20;
	//当前容量
	private int currentCapacity;
	//入库
	public void push(Cake cake){
		synchronized (this) {
			if(currentCapacity >= maxCapacity){
				try {
					this.wait();//
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			list.add(cake);
			currentCapacity++;
			System.out.println("入库,当前容量为:" + currentCapacity);
			this.notify();//
		}
	}
	//出库
	public void pop(){
		synchronized (this) {
			if(currentCapacity <= 0){//------------变
				try {
					this.wait();//
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			Cake cake = list.removeFirst();
			currentCapacity--;
			System.out.println("出库,当前容量为:" + currentCapacity + " -- " + cake);
			this.notify();//-------变
		}
	}
}

public class Producer extends Thread{
	private Store store;
	public Producer(Store store) {this.store = store;}
	@Override
	public void run() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		while(true){
			Cake cake = new Cake("桃李面包", sdf.format(new Date()));
			store.push(cake);
		}
	}
}
public class Consumer extends Thread{
	private Store store;	
	public Consumer(Store store) {this.store = store;}
	@Override
	public void run() {
		while(true){store.pop();}
	}
}
public static void main(String[] args) {
    Store store = new Store();
    Producer p = new Producer(store);
    Consumer c = new Consumer(store);
    p.start();
    c.start();
}

2、多个生产者多个消费者

public class Store{}//if 和notify变化
public static void main(String[] args) {
    Store store = new Store();
    Producer p1 = new Producer(store);
    Producer p2 = new Producer(store);
    Consumer c1 = new Consumer(store);
    Consumer c2 = new Consumer(store);
    p1.start();
    p2.start();
    c1.start();
    c2.start();
}

扩展:对象监视器

前面phone.wait();phone.notify();中的phone是对象监视器,而对象监视器可以是很多东西,像this、Consumer这些都可以是。但要在两个不同的线程里互相唤醒对方,就必须用相同的监视器。wait()是将当前线程阻塞,并且将其记录到监视器中(监视器不同自然就不知道要唤醒谁),notify()是将线程从阻塞状态唤醒(唤醒1个),进入就绪状态。notifyAll()是唤醒全部。

一般来说,安全锁用什么,对象监视器就用什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cat_lkh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值