方式一
package com.thread;
//生产消费者
class Sell {
int product;
public synchronized void produce() {
if (product >= 10) { //产品>=10停止生产 等待消费者消费产品
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
product++;
System.out.println(Thread.currentThread().getName() + "生产了第" + product + "个产品!");
notifyAll();//唤醒消费者
}
}
public synchronized void consume() {
if (product <= 0) {//产品<=0等待生产者生产产品
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "消费了第" + product + "个产品!");
product--;
notifyAll();//唤醒生产者
}
}
}
//生产者
class Produce implements Runnable {
Sell sell;
public Produce(Sell sell) {
this.sell = sell;
}
public void run() {
System.out.println("生产者开始生产产品!");
while (true) {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell.produce();
}
}
}
//消费者
class Consume implements Runnable {
Sell sell;
public Consume(Sell sell) {
this.sell = sell;
}
public void run() {
System.out.println("消费者开始消费产品!");
while (true) {
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell.consume();
}
}
}
public class TestProduceConsume {
public static void main(String[] args) {
Sell sell = new Sell();
Produce produce = new Produce(sell);
Consume consume = new Consume(sell);
Thread p1 = new Thread(produce);
Thread c1 = new Thread(consume);
Thread c2 = new Thread(consume);
p1.setName("生产者:");
c1.setName("消费者1:");
c2.setName("消费者2:");
p1.start();
c1.start();
c2.start();
}
}
方式二
package com.conncurrent;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//生产消费者
class Sell {
int product;
Lock lock;
Condition notEmpy;
Condition notFull;
public Sell(Lock lock) {
this.lock = lock;
notEmpy = lock.newCondition();
notFull = lock.newCondition();
}
public void produce() {
try {
lock.lock();
if (product >= 10) { // 产品>=10停止生产 等待消费者消费产品
try {
notEmpy.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
product++;
System.out.println(Thread.currentThread().getName() + "生产了第" + product + "个产品!");
notFull.signalAll();// 唤醒消费者
}
} finally {
lock.unlock();
}
}
public void consume() {
try {
lock.lock();
if (product <= 0) {// 产品<=0等待生产者生产产品
try {
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "消费了第" + product + "个产品!");
product--;
notEmpy.signalAll();// 唤醒生产者
}
} finally {
lock.unlock();
}
}
}
//生产者
class Produce implements Runnable {
Sell sell;
public Produce(Sell sell) {
this.sell = sell;
}
public void run() {
System.out.println("生产者开始生产产品!");
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell.produce();
}
}
}
//消费者
class Consume implements Runnable {
Sell sell;
public Consume(Sell sell) {
this.sell = sell;
}
public void run() {
System.out.println("消费者开始消费产品!");
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell.consume();
}
}
}
public class TestProduceConsume {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Sell sell = new Sell(lock);
Produce produce = new Produce(sell);
Consume consume = new Consume(sell);
Thread p1 = new Thread(produce);
Thread c1 = new Thread(consume);
Thread c2 = new Thread(consume);
p1.setName("生产者:");
c1.setName("消费者1:");
c2.setName("消费者2:");
p1.start();
c1.start();
c2.start();
}
}
方式三
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class ProducterConsumer {
final static BlockingQueue<Apple> queue = new ArrayBlockingQueue<Apple>(20);
public static void main(String[] args) {
Produce produce = new Produce(queue);
Consume consume = new Consume(queue);
new Thread(produce).start();
new Thread(consume).start();
}
}
class Produce implements Runnable {
BlockingQueue<Apple> queue;
public Produce(BlockingQueue<Apple> queue) {
this.queue = queue;
}
public void run() {
int i = 0;
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(150);
Apple apple = new Apple(++i);
queue.put(apple);//生产产品 阻塞方法
System.out.println("生产者开始生产产品:" + apple);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consume implements Runnable {
BlockingQueue<Apple> queue;
public Consume(BlockingQueue<Apple> queue) {
this.queue = queue;
}
public void run() {
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(400);
Apple apple = queue.take();//获取产品 阻塞方法
System.out.println("消费者开始消费产品:" + apple);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Apple {
public Apple(int id) {
super();
this.id = id;
}
int id;
@Override
public String toString() {
return "Apple [id=" + id + "]";
}
}
总结
生产消费者模式 主要是对线程间通信的应用,方式一调用wait()方法让当前线程进入WAITING状态的同时释放CPU控制权,当生产者生产了产品或消费者消费了产品后调用notifyAll()方法,会唤醒WAITING状态的线程,这样就会一直生产消费下去。方式二和方式一原理相同,使用了java.util.concurrent包下的ReentrantLock类,该类提供了创建Condition实现类的方法,该实现类ConditionObject在AbstractQueuedSynchronizer(AQS)下实现,其中对应实现了await()方法(对应wait()),signalAll()方法(对应notifyAll()),推荐使用此方式。方式三使用的是阻塞队列,线程的调度交给队列的完成,实际内部也是使用的Condition来通信的。