利用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实现生产者和消费者问题。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值