生产者与消费者问题是并发编程里面的经典问题,下面用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实现生产者和消费者问题。
生产者与消费者问题是并发编程里面的经典问题,下面用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实现生产者和消费者问题。