您的位置:首页 > 大数据 > 人工智能

利用wait()和notify()实现生产者与消费者问题

2016-05-13 11:42 701 查看
生产者与消费者问题是并发编程里面的经典问题,下面用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<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-family: Arial, Helvetica, sans-serif;"> //开启生产者和消费者线程</span>
producer.start(); 
consumer.start(); }
}
//生产者线程
class Producer extends Thread
{ private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> 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<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> 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();
}
}
}
}


所以从以上可以看出,notify()实际上是可以实现线程间通信,可以在一个线程里通知唤醒另一个线程里的wait,实质上也是因为他们 wait和notify操作的是同一对象,这也是因为wait和notify是相对于Object的。

这就是利用wait和notify实现生产者和消费者问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: