一、什么是生产者消费者问题?
生产者负责生产产品,消费者购买产品,当库存为空的时候,生产者继续生产,消费者购买数量要小于等于库存上限,不能出现,生产一次,消费两次,或者生产了没有消费的情况。
二、代码实例
Producer.java类
/**
* Created by yuandl on 2016-10-11.
*
/**
* 消费者
*/
public class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.destroy();
}
}
}
Consumer.java
/**
* 生产者
*/
public class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.create();
}
}
}
Resource.java
package product;
/**
* Created by yuandl on 2016-10-11./**
* 资源
*/
public class Resource {
private int number = 0;
private boolean flag = false;
/**
* 生产资源
*/
public synchronized void create() {
while (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(Thread.currentThread().getName() + "生产者------------" + number);
flag = true;
notifyAll();
}
/**
* 消费资源
*/
public synchronized void destroy() {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "消费者****" + number);
flag = false;
notifyAll();
}
}
ProducerConsumerTest.java
/**
* Created by yuandl on 2016-10-11.
*/
public class ProducerConsumerTest {
public static void main(String args[]) {
Resource resource = new Resource();
new Thread(new Consumer(resource)).start();
new Thread(new Consumer(resource)).start();
new Thread(new Producer(resource)).start();
new Thread(new Producer(resource)).start();
}
}
运行结果
三、问题研究
按照示例,生产者消费者交替运行,每次生产后都有对应的消费者,测试类创建实例,如果是生产者先运行,进入run()方法,进入create()方法,flag默认为false,number+1,生产者生产一个产品,flag置为true,同时调用notifyAll()方法,唤醒所有正在等待的线程,接下来如果还是生产者运行呢?这是flag为true,进入while循环,执行wait()方法,接下来如果是消费者运行的话,调用destroy()方法,这时flag为true,消费者购买了一次产品,随即将flag置为false,并唤醒所有正在等待的线程。这就是一次完整的多生产者对应多消费者的问题。
四、疑问
疑问1:为什么要用while?怎么不用if?
如果是一个生产者和一个消费者的情况,用if是可以的,但是使用if有局限。一旦触发了if判断条件,所有进入其中的线程都会变成等待的状态,容易造成只有生产,消费者都在等待的情况。
疑问2:为什么用notifyAll而不是notify?
直接运行notify会出现”假死”的状态,因为调用notify()方法一次只会唤醒一个优先级最高的线程。那么什么是线程的优先级呢?
线程会被划分为1到10,10个等级,数字越大优先级就越高,默认优先级是5。