利用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()的规范代码模板:
下面就贴一下wait和notify实现一个生产者线程和一个消费者线程并发执行的代码:
所以从以上可以看出,notify()实际上是可以实现线程间通信,可以在一个线程里通知唤醒另一个线程里的wait,实质上也是因为他们 wait和notify操作的是同一对象,这也是因为wait和notify是相对于Object的。
这就是利用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实现生产者和消费者问题。
相关文章推荐
- Selenium - Waits
- airdrop分享, Sender kSFOperationEventErrorOccured {
- Determining IP information for eth0... failed; no link present. Check cable?
- IIC 读写时候提示 timeout waiting for bus ready
- 2011版MacBook Air win7安装教程
- 查看当前的git用户名以及email
- failed to obtain a cell from its dataSource 解决方案
- poj1681Painter's Problem 增广矩阵消元法错误水过版
- http://blog.csdn.net/ta893115871/article/details/46955791/
- 【华为OJ】【054-Redraiment的走法】
- UVa - 514 Rails(栈模拟)
- UVa - 442 Matrix Chain Multiplication(栈模拟)
- TurboMail邮件系统资深技术支持杨工专访(二)
- HDU4300 Clairewd’s message 扩展kmp
- Leetcode 70. Climbing Stairs 爬楼梯 解题报告
- 图形绘制 Canvas Paint Path 详解
- flask发送邮件问题(yeah.net与Gmail设置的不同)
- photo mosaic 拼图马赛克
- leetcode@ [336] Palindrome Pairs (HashMap)
- fork wait