关于生产者和消费者的问题模型这里就不再详细描述
这里首先要定义三个类来分别代表生产者和消费者以及要生产或消费的物品
Producer.java
Consumer.java
Product.java
我们简单这么实现,假设生产者生产饼干或饮料当生产者生产完毕后通知消费者进行消费,当消费者消费完之后就通知生产者继续进行生产
实现如下:
使用main方法进行测试
Test.java
执行结果:
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
.....
即生产者每生产一次,就会通知消费者消费一次,消费者消费完之后,就会通知生产者继续生产
我这里采用的是一个生产者和一个消费者的情况,对于多个生产者和多个消费者的情况,其实就是多启动几个生产者和消费者线程,此外程序需要将唤醒线程的方法改为:notifyAll
这里首先要定义三个类来分别代表生产者和消费者以及要生产或消费的物品
Producer.java
Consumer.java
Product.java
我们简单这么实现,假设生产者生产饼干或饮料当生产者生产完毕后通知消费者进行消费,当消费者消费完之后就通知生产者继续进行生产
实现如下:
生产者Producer.java
public class Producer implements Runnable {
public Product pro;
public Producer(Product pro){
this.pro = pro;
}
@Override
public void run() {
// 生产者生产50次并控制让其在偶数次生产饼干,奇数次生产饮料
for(int i = 0; i < 50; i ++){
if(i % 2 == 0){
pro.set("饼干");
}else{
pro.set("饮料");
}
}
}
}
消费者Consumer.java
public class Consumer implements Runnable {
private Product pro;
public Consumer(Product pro){
this.pro = pro;
}
@Override
public void run() {
// 消费者消费50次
for(int i = 0; i < 50; i ++){
pro.get();
}
}
}
产品Product.java
public class Product {
// 所生产的产品
private String product;
// 定义信号量,是否有产品,默认为空即true
private boolean isEmpty = true;
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
// 生产
public void produce(String product) {
synchronized (this) {
while (!isEmpty) {
// 如果不为空,等待消费者消费
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setProduct(product);
System.out.println("生产者生产------>" + this.getProduct());
isEmpty = false;
this.notify();
}
}
// 消费
public void consume() {
synchronized (this) {
while (isEmpty) {
// 如果为空,等待生产者生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费------>" + this.getProduct());
isEmpty = true;
this.notify();
}
}
}
使用main方法进行测试
Test.java
public class Test {
public static void main(String[] args) {
// 产品
Product pro = new Product();
// 定义一个生产者
Producer producer = new Producer(pro);
// 定义一个消费者
Consumer consumer = new Consumer(pro);
// 启动生产者线程
new Thread(producer).start();
// 启动消费者线程
new Thread(consumer).start();
}
}
执行结果:
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
.....
即生产者每生产一次,就会通知消费者消费一次,消费者消费完之后,就会通知生产者继续生产
我这里采用的是一个生产者和一个消费者的情况,对于多个生产者和多个消费者的情况,其实就是多启动几个生产者和消费者线程,此外程序需要将唤醒线程的方法改为:notifyAll
这里需要注意的是wait()、notify()、notifyAll(),这三个方法属于Object 不属于 Thread,这三个方法必须由同步监视对象来调用,即调用wait、notify、notifyAll方法的对象必须是synchronized所监视的对象
在上面我们采用了synchronized来进行线程的同步实现了生产者和消费者问题,现在我们采用jdk1.5版本以上采用的同步锁进行一次实现,同步锁和synchronized的效果一样都能够实现线程的同步,同时其功能更加强大。现在我们就用同步锁的方式来实现一下生产这和消费者问题,与之前不同的是这里要解决的一个问题就是,线程之间的通信怎么进行处理,由于同步锁没有像synchronized一样存在对固定对象的监视,因此wait、notify、notifyAll都不能再使用了。这里同步锁提供了另外的可代替的方式,就是Condition,Condition通过Lock的对象的newCondition方法产生,可起到同步监视器的作用。简单的说:Lock代替了同步方法或同步代码块,Condition代替了同步监视器的功能
下面我们就将之前的实现进行一下修改:
生产者:Producer.java
消费者:Consumer.java
都不用变
Product.java修改如下
public class Product {
// 产品
private String product;
// 定义信号量,是否有产品
private boolean isEmpty = true;
// 定义同步锁
private final ReentrantLock lock = new ReentrantLock();
// 获取Condition对象
private final Condition condition = lock.newCondition();
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
// 生产
public void produce(String product) {
lock.lock();
try {
while (!isEmpty) {
// 等待消费者消费
condition.await();
}
this.setProduct(product);
System.out.println("生产者生产------>" + this.getProduct());
isEmpty = false;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
// 消费
public void consume() {
lock.lock();
try {
while (isEmpty) {
// 等待生产者生产
condition.await();
}
System.out.println("消费者消费------>" + this.getProduct());
isEmpty = true;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
使用main方法测试和之前的结果一致