利用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()的规范代码模板:

[java]  view plain  copy
  1. synchronized (sharedObject) { //锁住操作对象  
  2.     while (condition) { //当某个条件下  
  3.     sharedObject.wait(); //进入wait  
  4.           
  5.     }   
  6.     // 做了什么事,就可以激活  
  7.     shareObject.notify();  
  8. }   


下面就贴一下wait和notify实现一个生产者线程和一个消费者线程并发执行的代码:

[java]  view plain  copy
  1. import java.util.LinkedList;   
  2. import java.util.Queue;   
  3. import java.util.Random;   
  4.   
  5. public class ProducerConsumerInJava {   
  6. public static void main(String args[]) {   
  7.   System.out.println("How to use wait and notify method in Java");   
  8.   System.out.println("Solving Producer Consumper Problem");   
  9.   Queue<Integer> buffer = new LinkedList<>();   
  10.   int maxSize = 10;   
  11.   Thread producer = new Producer(buffer, maxSize, "PRODUCER");   
  12.   Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");<span style="font-family: Arial, Helvetica, sans-serif;"> </span>  
[java]  view plain  copy
  1. <span style="font-family: Arial, Helvetica, sans-serif;"//开启生产者和消费者线程</span>  
[java]  view plain  copy
  1. producer.start();   
[java]  view plain  copy
  1. consumer.start(); }   
[java]  view plain  copy
  1. //生产者线程  
  2. class Producer extends Thread   
  3. private Queue<Integer> queue;   
  4.   private int maxSize;   
  5.   public Producer(Queue<Integer> queue, int maxSize, String name){   
  6.    super(name); this.queue = queue; this.maxSize = maxSize;   
  7.   }   
  8.   @Override public void run()   
  9.   {   
  10.    while (true)   
  11.     {   
  12.      synchronized (queue) {   
  13.       while (queue.size() == maxSize) { //当缓存区满的时候  
  14.        try {   
  15.         //进入wait  
  16.         queue.wait();   
  17.        } catch (Exception ex) {   
  18.         ex.printStackTrace();   
[java]  view plain  copy
  1. }   
  2.  }   
[java]  view plain  copy
  1. //缓存区不为空的时候就可以继续生产,生产后唤醒消费者线程的wait  
  2.  queue.add(i);   
[java]  view plain  copy
  1.      queue.notifyAll();   
  2.    }   
  3.   }   
  4.  }   
  5. }   
[java]  view plain  copy
  1. //消费者线程  
  2. class Consumer extends Thread {   
  3.   private Queue<Integer> queue;   
  4.   private int maxSize;   
  5.   public Consumer(Queue<Integer> queue, int maxSize, String name){   
  6.    super(name);   
  7.    this.queue = queue;   
  8.    this.maxSize = maxSize;   
  9.   }   
  10.   @Override public void run() {   
  11.    while (true) {   
  12.     synchronized (queue) {   
  13.      while (queue.isEmpty()) { //当缓存区为空的时候  
  14.         
  15.       try {   
  16.        queue.wait(); //进入wait  
  17.       } catch (Exception ex) {   
  18.        ex.printStackTrace();   
  19.       }   
  20.      }   
[java]  view plain  copy
  1.     //当缓存区不为空的时候,就可以唤醒所有的wait的消费者线程或者生产者线程  
  2.     queue.notifyAll();   
  3.   }   
  4.  }   
  5. }   

所以从以上可以看出,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()的规范代码模板:

[java]  view plain  copy
  1. synchronized (sharedObject) { //锁住操作对象  
  2.     while (condition) { //当某个条件下  
  3.     sharedObject.wait(); //进入wait  
  4.           
  5.     }   
  6.     // 做了什么事,就可以激活  
  7.     shareObject.notify();  
  8. }   


下面就贴一下wait和notify实现一个生产者线程和一个消费者线程并发执行的代码:

[java]  view plain  copy
  1. import java.util.LinkedList;   
  2. import java.util.Queue;   
  3. import java.util.Random;   
  4.   
  5. public class ProducerConsumerInJava {   
  6. public static void main(String args[]) {   
  7.   System.out.println("How to use wait and notify method in Java");   
  8.   System.out.println("Solving Producer Consumper Problem");   
  9.   Queue<Integer> buffer = new LinkedList<>();   
  10.   int maxSize = 10;   
  11.   Thread producer = new Producer(buffer, maxSize, "PRODUCER");   
  12.   Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");<span style="font-family: Arial, Helvetica, sans-serif;"> </span>  
[java]  view plain  copy
  1. <span style="font-family: Arial, Helvetica, sans-serif;"//开启生产者和消费者线程</span>  
[java]  view plain  copy
  1. producer.start();   
[java]  view plain  copy
  1. consumer.start(); }   
[java]  view plain  copy
  1. //生产者线程  
  2. class Producer extends Thread   
  3. private Queue<Integer> queue;   
  4.   private int maxSize;   
  5.   public Producer(Queue<Integer> queue, int maxSize, String name){   
  6.    super(name); this.queue = queue; this.maxSize = maxSize;   
  7.   }   
  8.   @Override public void run()   
  9.   {   
  10.    while (true)   
  11.     {   
  12.      synchronized (queue) {   
  13.       while (queue.size() == maxSize) { //当缓存区满的时候  
  14.        try {   
  15.         //进入wait  
  16.         queue.wait();   
  17.        } catch (Exception ex) {   
  18.         ex.printStackTrace();   
[java]  view plain  copy
  1. }   
  2.  }   
[java]  view plain  copy
  1. //缓存区不为空的时候就可以继续生产,生产后唤醒消费者线程的wait  
  2.  queue.add(i);   
[java]  view plain  copy
  1.      queue.notifyAll();   
  2.    }   
  3.   }   
  4.  }   
  5. }   
[java]  view plain  copy
  1. //消费者线程  
  2. class Consumer extends Thread {   
  3.   private Queue<Integer> queue;   
  4.   private int maxSize;   
  5.   public Consumer(Queue<Integer> queue, int maxSize, String name){   
  6.    super(name);   
  7.    this.queue = queue;   
  8.    this.maxSize = maxSize;   
  9.   }   
  10.   @Override public void run() {   
  11.    while (true) {   
  12.     synchronized (queue) {   
  13.      while (queue.isEmpty()) { //当缓存区为空的时候  
  14.         
  15.       try {   
  16.        queue.wait(); //进入wait  
  17.       } catch (Exception ex) {   
  18.        ex.printStackTrace();   
  19.       }   
  20.      }   
[java]  view plain  copy
  1.     //当缓存区不为空的时候,就可以唤醒所有的wait的消费者线程或者生产者线程  
  2.     queue.notifyAll();   
  3.   }   
  4.  }   
  5. }   

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


这就是利用wait和notify实现生产者和消费者问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值