生产者与消费者问题是并发编程里面的经典问题,下面用wait()和notify()来实现消费者线程和生产者线程的并发执行。
说之前先讲几个概念:
wait()与sleep()的区别:
1.首先sleep()是Thread()类的方法,而wait()是Object类的方法,包括notify(),notifyAll()都是Object类的方法
2.sleep()方法是休眠,阻塞线程的同时仍然会持有锁,也就是说它休眠期间其他线程仍然无法获得锁,同时sleep()休眠时自动醒 的;而调用wait()方法时,则自动释放锁,也就是其他线程可以获得锁,而且wait()是无法自动醒的,只有通过notify()或 notifyAll() 才行。
notify()与notifyAll()的区别
notify()一次只能激活一个对这个对象进行wait()的线程,当多个线程都对此对象wait()时,是随机挑一个notify(),而notifyAll()是一次 性激活所以对此对象进行wait()的线程。
接下来说说利用wait()和notify()来实现生产者和消费者并发问题:
显然要保证生产者和消费者并发运行不出乱,主要要解决:当生产者线程的缓存区为满的时候,就应该调用wait()来停止生产者继续生产,而当生产者满的缓冲区被消费者消费掉一块时,则应该调用notify()唤醒生产者,通知他可以继续生产;同样,对于消费者,当消费者线程的缓存区为空的时候,就应该调用wait()停掉消费者线程继续消费,而当生产者又生产了一个时就应该调用notify()来唤醒消费者线程通知他可以继续消费了。
当然我们必须在wait()和notify()的时候锁住我们所要操作的对象,这里即缓存区,下面是一个使用wait()的notify()的规范代码模板:
synchronized (sharedObject) { //锁住操作对象
while (condition) { //当某个条件下
sharedObject.wait(); //进入wait
}
// 做了什么事,就可以激活
shareObject.notify();
}
下面就贴一下wait和notify实现一个生产者线程和一个消费者线程并发执行的代码:
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class ProducerConsumerInJava {
public static void main(String args[]) {
System.out.println("How to use wait and notify method in Java");
System.out.println("Solving Producer Consumper Problem");
Queue buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
//开启生产者和消费者线程
producer.start();
consumer.start(); }
}
//生产者线程
class Producer extends Thread
{ private Queue queue;
private int maxSize;
public Producer(Queue queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
@Override public void run()
{
while (true)
{
synchronized (queue) {
while (queue.size() == maxSize) { //当缓存区满的时候
try {
//进入wait
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
//缓存区不为空的时候就可以继续生产,生产后唤醒消费者线程的wait
queue.add(i);
queue.notifyAll();
}
}
}
}
//消费者线程
class Consumer extends Thread {
private Queue queue;
private int maxSize;
public Consumer(Queue queue, int maxSize, String name){
super(name);
this.queue = queue;
this.maxSize = maxSize;
}
@Override public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) { //当缓存区为空的时候
try {
queue.wait(); //进入wait
} catch (Exception ex) {
ex.printStackTrace();
}
}
//当缓存区不为空的时候,就可以唤醒所有的wait的消费者线程或者生产者线程
queue.notifyAll();
}
}
}
}
这就是利用wait和notify实现生产者和消费者问题。