生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型最重要的作用 。
/**
* 生产者消费者模型
* 通过wait、notify实现
* 缓冲区满和为空时都调用wait()方法等待,当生产者生产了一个产品或者消费者消费了一个产品之后会唤醒所有线程。
*/
public class ProducerConsumer1 {
private static Integer count = 0;
private static final Integer FULL = 10;//缓冲区大小
private static String LOCK = "lock";
public static void main(String[] args) {
ProducerConsumer1 producerConsumer = new ProducerConsumer1();
new Thread(producerConsumer.new Producer()).start();
new Thread(producerConsumer.new Producer()).start();
new Thread(producerConsumer.new Producer()).start();
new Thread(producerConsumer.new Consumer()).start();
}
//生产者-生产数据
class Producer implements Runnable{
@Override
public void run() {
while (true){
synchronized (LOCK){
while (count == FULL) {//如果缓冲区已满
try {
LOCK.wait();//生产者等待
} catch (Exception e) {
e.printStackTrace();
}
}
count++;//生产一个数据
System.out.println(Thread.currentThread().getName() + "生产者生产,目前总共有" + count);
LOCK.notifyAll();//生产完毕,唤醒消费者
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者-消费数据
class Consumer implements Runnable{
@Override
public void run() {
while(true){
synchronized (LOCK){
while (count == 0) {//如果缓冲区为空
try {
LOCK.wait();//消费者等待
} catch (Exception e) {
e.printStackTrace();
}
}
count--;//消费一个数据
System.out.println(Thread.currentThread().getName() + "消费者消费,目前总共有" + count);
LOCK.notifyAll();//消费完毕,唤醒生产者
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
方式二:
/**
* 生产者消费者模型
* 通过BlockQueue实现
* 当一个线程对已经满了的阻塞队列进行入队操作时会阻塞,
* 除非有另外一个线程进行了出队操作,当一个线程对一个空的阻塞队列进行出队操作时也会阻塞,除非有另外一个线程进行了入队操作。
*/
public class ProducerConsumer {
private static Integer count = 0;
//创建一个阻塞队列
final BlockingQueue blockingQueue = new ArrayBlockingQueue<>(10);
public static void main(String[] args) {
ProducerConsumer producerConsumer = new ProducerConsumer();
new Thread(producerConsumer.new Producer()).start();
new Thread(producerConsumer.new Producer()).start();
new Thread(producerConsumer.new Consumer()).start();
}
//生产者-生产数据
class Producer implements Runnable{
@Override
public void run() {
while (true){
try {
count++;
blockingQueue.put(count);//生产数据放入阻塞队列
System.out.println(Thread.currentThread().getName()+ "生产者生产,目前总共有" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者-消费数据
class Consumer implements Runnable{
@Override
public void run() {
//消费
while (true){
try {
blockingQueue.take();//从队列中移除一个元素,若队列为空,阻塞
count--;
System.out.println(Thread.currentThread().getName()
+ "消费者消费,目前总共有" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}