学习记录326@Java生产者-消费者多线程模型

it2023-06-28  65

共享变量为手机类,生产者生产手机,消费者消费手机,要求生产一部消费一部,不能错乱

//共享变量 package com.dream.test03; public class Phone { private String name; private double price; private boolean store;//是否有货 public Phone() { // TODO Auto-generated constructor stub } public Phone(String name, double price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public boolean isStore() { return store; } public void setStore(boolean store) { this.store = store; } @Override public String toString() { return "Phone [name=" + name + ", price=" + price + "]"; } } //生产者 package com.dream.test03; public class Producer extends Thread { private Phone phone; private static boolean flag; public Producer() { } public Producer(Phone phone) { this.phone = phone; } @Override public void run() { // TODO Auto-generated method stub while(true){ synchronized (phone) { while (phone.isStore()) { try { phone.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(flag){ phone.setName("小米"); phone.setPrice(1999); }else { phone.setName("华为"); phone.setPrice(3999); } flag=!flag; phone.setStore(true); phone.notifyAll(); } } } } //消费者 package com.dream.test03; public class Consumer extends Thread { private Phone phone; public Consumer() { } public Consumer(Phone phone) { this.phone = phone; } @Override public void run() { // TODO Auto-generated method stub while(true){ synchronized (phone) { while (!phone.isStore()) { try { phone.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(phone.getName()+"--"+phone.getPrice()); phone.setStore(false); phone.notifyAll(); } } } } //测试 package com.dream.test03; public class Test01 { public static void main(String[] args) { Phone phone = new Phone(); Producer producer1 = new Producer(phone); Consumer consumer1 = new Consumer(phone); Producer producer2 = new Producer(phone); Consumer consumer2 = new Consumer(phone); producer1.start(); consumer1.start(); producer2.start(); consumer2.start(); } }

关于 wait和notify/notifyAll

JVM底层原理:JVM会为每个对象维护一个入口集,用于存储申请该对象内部锁的线程;还要维护一个等待集队列,用于存储该对象上的等待线程,当 someObject.wait()执行的时候,将当前线程暂停并释放对象锁,然后将此线程加入到等待集中;然后执行一个对象的someObject.notifyAll(),方法会该对象的等待集中所有线程被唤醒(notify是唤醒任意线程,在实际开发中最好用notifyAll),但是被唤醒的线程此时仍然在等待队列中,直到其再次抢到对象锁后,someObject.wait()才会将这个等待线程移出等待集,someObject.wait()才会结束,继续执行后面的代码。

注意点: 1、保护条件是包含共享变量的布尔表达式 2、一个线程只有在持有一个对象的对象锁时,才能调用这个对象的wait/notify方法,执行wait方法即刻就会释放对象锁,但是执行notify方法要等同步代码块执行完了之后才释放对象锁 3、等待线程被唤醒到再次持有对象锁的过程中,可能又被唤醒线程抢到对象锁,并且更新保护条件再次不成立,然后如果被唤醒的等待线程拿到对象锁继续执行后,是有问题的,因此,使用while条件而不是if判断,这样就可以再次判断一下保护条件是否成立,如果不成立,还是得继续等待;

最新回复(0)