生产者与消费者模型
线程间的通信: 一个线程完成了自己的任务时,要通知另外一个线程去完成另外一个任务.
生产者与消费者模型
问题一:出现了线程安全问题。 价格错乱了…
问题二:消费者线程先抢到CPU执行权,消费了一堆产品后,而生产者线程才抢到CPU开始生产产品
或者,生产者先抢到CPU,但是生产了一堆产品都没有被消费,等到消费者抢到CPU才开始消费
这样的情况在计算机里不符合任务执行的有序性
比如A,B线程共同完成一个任务,但是A完成一部分后,必须要等B线程也完成一部分后,A才能继续完成剩下的
解决方案:A完成一部分后,让A进入等待状态,B获得CPU开始执行任务,
这就需要一个共同的锁对象,根据锁对象创建一个线程等待池
在下面的示例中,我们以共同的对象 Product类对象p为锁对象,
生产者生产一个产品就进入等待池,并唤醒消费者,
消费者消费完之后,唤醒生产者,生产者再继续生产。
wait(): 等待 如果线程执行了wait方法,那么该线程会进入等待的状态,
等待状态下的线程必须要被其他线程调用notify方法才能唤醒。
notify(): 唤醒 唤醒线程池等待线程其中的一个。
notifyAll() : 唤醒线程池所有等待 线程。
注意的事项:
1. wait方法与notify方法是属于Object对象 的。
2. wait方法与notify方法必须要在同步代码块或者是同步函数中才能 使用。
3. wait方法与notify方法必需要由共同的锁对象调用。
class Product {// 产品类
String name;// 产品名
double price;// 产品价格
boolean flag = true;// flag决定要不要进行生产,默认一创建Pcoduct对象就开始生产
public Product() {
}
public Product(String name, double price) {
this.name = name;
this.price = price;
}
}
class Producer implements Runnable {// 生产者
Product p;// 声明一个产品,暂时不知道生产者具体要生产的是什么
public Producer() {
}
public Producer(Product p) {
this.p = p;
}
@Override
public void run() {
int i = 0;// 定义一个自增变量,根据i的值决定要生产什么产品
while (true) {
synchronized (p) {// 因为两个线程要通信,必须要用共同的锁对象
if (p.flag) {
if (i % 2 == 0) {
p.name = "苹果";
p.price = 2.0;
} else {
p.name = "香蕉";
p.price = 3.0;
}
System.out.println("生产者生产了" + p.name + p.price + "元");
i++;
p.flag = false;
p.notify();// 唤醒消费者
} else {
// 每生产一个产品就进入等待状态
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Customer implements Runnable {
Product p;
public Customer() {
}
public Customer(Product p) {
this.p = p;
}
@Override
public void run() {
while (true) {
synchronized (p) {
if (!(p.flag)) {
System.out.println("消费者消费了" + p.name + p.price + "元");
p.flag = true;
p.notify();// 唤醒生产者者
} else {
// 每消费一个产品就等待
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Demo4 {
public static void main(String[] args) {
Product p = new Product();
Producer pro = new Producer(p);
Customer cus = new Customer(p);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(cus);
t1.start();
t2.start();
}
}
产生的问题
不能有序地进行生产和消费
使用了flag变量和wait与notify方法后,解决了生产者和消费者之间的通信问题,使生产和消费变得有序,生产一个,消费一个