生产者–消费者模式
生产者--消费者模式是使用多线程的典型操作案例,每生产一个对象消费者就取走一个对象,生产者不断生产对象,消费者不断消费对象
想要实现生产者--消费者模式,是要使用到synchronized(同步)以及Object对象的wait()、notify()/notifyAll()方法
使用synchronized是为了防止值错乱;
使用wait()和notify()/notifyAll()是为了解决值重复的问题
看以下代码:
package threaddemo;
public class Food {
private String name;
private float price;
private boolean flag = false;
public Food() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public void set(String name,float price) throws InterruptedException {
synchronized (this){
if(flag){
this.wait();
}
this.setName(name);
Thread.sleep(300);
this.setPrice(price);
this.flag = true;
this.notify();
}
}
public void get() throws InterruptedException {
synchronized(this){
if(!flag){
this.wait();
}
System.out.println(this.name+"--->"+this.price);
Thread.sleep(300);
this.flag = false;
this.notify();
}
}
}
package threaddemo;
public class Consumer implements Runnable {
private Food food;
Consumer(Food food){
this.food = food;
}
@Override
public void run() {
for(int i=0;i<100;i++){
try {
food.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package threaddemo;
public class Producter implements Runnable {
private Food food;
Producter(Food food){
this.food = food;
}
@Override
public void run() {
for(int i=0;i<100;i++){
if(i%2==0){
try {
food.set("糖醋排骨",45.0f);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
try {
food.set("清蒸山药", 38.0f);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package threaddemo;
public class Test {
public static void main(String[] args) {
Food food = new Food();
Producter producter = new Producter(food);
Consumer consumer = new Consumer(food);
new Thread(producter).start();
new Thread(consumer).start();
}
}
在以上代码中,我们实现的是一个厨师炒菜以及客户吃菜的一个生产者--消费者实例,在上述中:
解决值错乱的问题是在Food类使用synchronized代码块将setName和setPrice放在一个锁里面。这样无论是那个线程抢到了CUP,这个线程中run方法里面的set方法会完整的执行,不会中途因为阻塞而产生值错乱。
解决重复取值的问题是使用wait、notify和flag(改变状态的变量)来解决的。首先看一下方法的用法(这三个方法必须在synchronized函数或者synchronized block中进行调用)
wait()后,线程会释放它所占有的“锁标志”,从而是线程所在的对象中的其他synchronized数据可以被别的线程使用。
notify()会唤醒第一个等待的线程。
notifyAll()唤醒全部等待的线程,那个优先级高,就先执行那个
然后在以上的操作中应该增加一个标志位,此标志位应有两种状态,可以使用boolean类型来表示:
1. 如果boolean的值是false的话表示可以生产,不能取走
2. 如果boolean的值是true的话表示可以取走,不能生产
然后在以上的操作中应该增加一个标志位,此标志位应有两种状态,可以使用boolean类型来表示:
1. 如果boolean的值是false的话表示可以生产,不能取走
2. 如果boolean的值是true的话表示可以取走,不能生产