笔记本新品的新品有哪些?

本帖子已过去太久远了,不再提供回复功能。如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例 - ImportNew
| 标签: , ,
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。
在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。
我们可以利用wait()来让一个线程在某些条件下暂停运行。例如,在生产者消费者模型中,生产者线程在缓冲区为满的时候,消费者在缓冲区为空的时候,都应该暂停运行。如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待中的线程重新开始运行。不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。但如果多个线程在等待这个信号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。
在这篇文章中你将会学到如何使用 wait、notify 和 notifyAll 来实现线程间的通信,从而解决生产者消费者问题。如果你想要更深入地学习Java中的多线程同步问题,我强烈推荐阅读Brian Goetz所著的《 | 》,不读这本书你的 Java 多线程征程就不完整哦!这是我最向Java开发者推荐的书之一。
如何使用Wait
尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单。如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题,我几乎可以肯定他们中的大多数都会无所适从或者犯下一些错误,例如在错误的地方使用 synchronized 关键词,没有对正确的对象使用wait,或者没有遵循规范的代码方法。说实话,这个问题对于不常使用它们的程序员来说确实令人感觉比较头疼。
第一个问题就是,我们怎么在代码里使用wait()呢?因为wait()并不是Thread类下的函数,我们并不能使用Thread.call()。事实上很多Java程序员都喜欢这么写,因为它们习惯了使用Thread.sleep(),所以他们会试图使用wait() 来达成相同的目的,但很快他们就会发现这并不能顺利解决问题。正确的方法是对在多线程间共享的那个Object来使用wait。在生产者消费者问题中,这个共享的Object就是那个缓冲区队列。
第二个问题是,既然我们应该在synchronized的函数或是对象里调用wait,那哪个对象应该被synchronized呢?答案是,那个你希望上锁的对象就应该被synchronized,即那个在多个线程间被共享的对象。在生产者消费者问题中,应该被synchronized的就是那个缓冲区队列。(我觉得这里是英文原文有问题……本来那个句末就不应该是问号不然不太通……)
永远在循环(loop)里调用 wait 和 notify,不是在 If 语句
现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生成数据,或者缓冲区为空的时候消费者开始小号数据。所以记住,永远在while循环而不是if语句中使用wait!我会推荐阅读《》,这是关于如何正确使用wait和notify的最好的参考资料。
基于以上认知,下面这个是使用wait和notify函数的规范代码模板:
// The standard idiom for calling the wait method in Java
synchronized (sharedObject) {
while (condition) {
sharedObject.wait();
// (Releases lock, and reacquires on wakeup)
// do action based upon condition e.g. take or put into queue
就像我之前说的一样,在while循环里使用wait的目的,是在线程被唤醒的前后都持续检查条件是否被满足。如果条件并未改变,wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题。
Java wait(), notify(), notifyAll() 范例
下面我们提供一个使用wait和notify的范例程序。在这个程序里,我们使用了上文所述的一些代码规范。我们有两个线程,分别名为PRODUCER(生产者)和CONSUMER(消费者),他们分别继承了了Producer和Consumer类,而Producer和Consumer都继承了Thread类。Producer和Consumer想要实现的代码逻辑都在run()函数内。Main线程开始了生产者和消费者线程,并声明了一个LinkedList作为缓冲区队列(在Java中,LinkedList实现了队列的接口)。生产者在无限循环中持续往LinkedList里插入随机整数直到LinkedList满。我们在while(queue.size == maxSize)循环语句中检查这个条件。请注意到我们在做这个检查条件之前已经在队列对象上使用了synchronized关键词,因而其它线程不能在我们检查条件时改变这个队列。如果队列满了,那么PRODUCER线程会在CONSUMER线程消耗掉队列里的任意一个整数,并用notify来通知PRODUCER线程之前持续等待。在我们的例子中,wait和notify都是使用在同一个共享对象上的。
import java.util.LinkedL
import java.util.Q
import java.util.R
* Simple Java program to demonstrate How to use wait, notify and notifyAll()
* method in Java by solving producer consumer problem.
* @author Javin Paul
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&);
producer.start(); consumer.start(); }
* Producer Thread will keep producing values for Consumer
* to consumer. It will use wait() method when Queue is full
* and use notify() method to send notification to Consumer
* @author WINDOWS 8
class Producer extends Thread
{ private Queue&Integer&
private int maxS
public Producer(Queue&Integer& queue, int maxSize, String name){
super(name); this.queue = this.maxSize = maxS
@Override public void run()
while (true)
synchronized (queue) {
while (queue.size() == maxSize) {
System.out .println(&Queue is full, & + &Producer thread waiting for & + &consumer to take something from queue&);
queue.wait();
} catch (Exception ex) {
ex.printStackTrace(); }
Random random = new Random();
int i = random.nextInt();
System.out.println(&Producing value : & + i); queue.add(i); queue.notifyAll();
* Consumer Thread will consumer values form shared queue.
* It will also use wait() method to wait if queue is
* empty. It will also use notify method to send
* notification to producer thread after consuming values
* from queue.
* @author WINDOWS 8
class Consumer extends Thread {
private Queue&Integer&
private int maxS
public Consumer(Queue&Integer& queue, int maxSize, String name){
super(name);
this.queue =
this.maxSize = maxS
@Override public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println(&Queue is empty,& + &Consumer thread is waiting& + & for producer thread to put something in queue&);
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
System.out.println(&Consuming value : & + queue.remove()); queue.notifyAll();
为了更好地理解这个程序,我建议你在debug模式里跑这个程序。一旦你在debug模式下启动程序,它会停止在PRODUCER或者CONSUMER线程上,取决于哪个线程占据了CPU。因为两个线程都有wait()的条件,它们一定会停止,然后你就可以跑这个程序然后看发生什么了(很有可能它就会输出我们以上展示的内容)。你也可以使用Eclipse里的Step into和Step over按钮来更好地理解多线程间发生的事情。
本文重点:
1. 你可以使用wait和notify函数来实现线程间通信。你可以用它们来实现多线程(&3)之间的通信。
2. 永远在synchronized的函数或对象里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。
3. 永远在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。
4. 永远在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。
5. 基于前文提及的理由,更倾向用 notifyAll(),而不是 notify()。
这是关于Java里如何使用wait, notify和notifyAll的所有重点啦。你应该只在你知道自己要做什么的情况下使用这些函数,不然Java里还有很多其它的用来解决同步问题的方案。例如,如果你想使用生产者消费者模型的话,你也可以使用BlockingQueue,它会帮你处理所有的线程安全问题和流程控制。如果你想要某一个线程等待另一个线程做出反馈再继续运行,你也可以使用。如果你只是想保护某一个资源的话,你也可以使用Semaphore。
原文链接:
- 译文链接: [ 转载请保留原文出处、译者和译文链接。]
关于作者:
感谢大神分享
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
– 好的话题、有启发的回复、值得信赖的圈子
– 写了文章?看干货?去头条!
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 活跃 & 专业的翻译小组
– 国内外的精选博客文章
– UI,网页,交互和用户体验
– JavaScript, HTML5, CSS
– 专注Android技术分享
– 专注iOS技术分享
– 专注Java技术分享
– 专注Python技术分享
& 2017 ImportNewjava线程wait和notifyAll方法的简单使用 -
- ITeye技术网站
博客分类:
今天温习了java线程的知识,看到wait和notify时,有感而发,不说废话,直接上代码。
package com.zx.thread.
import java.util.concurrent.*;
public class UsingWaitAndNotify {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
Cup cup = new Cup("水晶杯");
// 开始时,杯子未洗干净,因此泡茶人被挂起
exec.execute(new TeaMaker(cup));
// 洗杯子的人发现杯子是不干净的,于是开始洗杯子,
// 洗完杯子后,通知泡茶的人,可以泡茶了
exec.execute(new Washer(cup));
exec.shutdown();
* 我们列举一个洗杯子泡茶的流程 1、先洗干净杯子,然后才能泡茶 2、ok,茶泡好了,慢慢品尝一番,然后倒掉茶叶,准备重新泡一杯茶 3、重复第一步和第二步
* @author maping
class Cup {
private volatile boolean washed =
public Cup() {
public Cup(String name) {
this.name =
public synchronized void wash(Runnable owner) throws InterruptedException {
System.out.println(owner.getClass().getSimpleName() + "&&正在洗杯子");
Thread.sleep(3000);
// 杯子洗干净了,可以泡茶了
notifyAll();
System.out.println(owner.getClass().getSimpleName()
+ "&&杯子洗干净了,你可以拿去泡茶用了");
public synchronized void makeTea(Runnable owner)
throws InterruptedException {
System.out.println(owner.getClass().getSimpleName() + "&&准备泡茶");
// 如果杯子未被洗干净,那么我只有等待杯子被洗干净才能开始泡茶
while (!washed) {
System.out.println(owner.getClass().getSimpleName()
+ "&&很无奈,杯子是脏的,我只有等它被洗干净,我自己懒得动手洗");
System.out.println(owner.getClass().getSimpleName()
+ "&&终于拿到干净的杯子了,开始泡一杯清茶");
public String toString() {
return "Cup of " + this.
class Washer implements Runnable {
public Washer(Cup cup) {
this.cup =
public void run() {
System.out.println(this.getClass().getSimpleName() + "&&我是清洁工,开始洗杯子");
cup.wash(this);
} catch (InterruptedException e) {
e.printStackTrace();
class TeaMaker implements Runnable {
public TeaMaker(Cup cup) {
this.cup =
public void run() {
System.out.println(this.getClass().getSimpleName() + "&&我是泡茶工,我开始泡茶");
cup.makeTea(this);
} catch (InterruptedException e) {
e.printStackTrace();
运行结果:
TeaMaker&&我是泡茶工,我开始泡茶
TeaMaker&&准备泡茶
TeaMaker&&很无奈,杯子是脏的,我只有等它被洗干净,我自己懒得动手洗
Washer&&我是清洁工,开始洗杯子
Washer&&正在洗杯子
Washer&&杯子洗干净了,你可以拿去泡茶用了
TeaMaker&&终于拿到干净的杯子了,开始泡一杯清茶
浏览: 280996 次
来自: 成都
看了半天,真的是半天,总算是把这些概念都理清了,谢谢博主
请问下,在内外层事务均是REQUIRED的情况下,内层事务抛出 ...
吊炸天啊!
很有用,谢谢了Java Object.notifyAll()方法
当前位置:
>> Java Object.notifyAll()方法
Java Object.notifyAll()方法
Java Object.notifyAll()方法用法实例教程。
java.lang.Object.notifyAll()&唤醒所有线程都在等待这个对象的监视器。一个线程等待对象的监视器上调用wait方法之一。
被唤醒的线程将无法继续进行,直到当前的线程放弃此对象上的锁。被唤醒的线程将在通常的方式与任何其他线程可能会积极地争相在此对象上同步竞争,例如,锁定此对象的下一个线程被唤醒的线程享受没有可靠的特权或劣势。
这个方法应该只能被一个线程是这个对象的监视器的所有者。
以下是java.lang.Object.notifyAll()方法的声明
public final void notifyAll()
此方法不返回一个值。
IllegalMonitorStateException&--&如果当前线程不是这个对象监视器的所有者。
下面的例子说明了如何使用lang.Object.notifyAll()方法。
package com.
import java.util.C
import java.util.LinkedL
import java.util.L
public class ObjectDemo extends Object {
private List synchedL
public ObjectDemo() {
// create a new synchronized list to be used
synchedList = Collections.synchronizedList(new LinkedList());
// method used to remove an element from the list
public String removeElement() throws InterruptedException {
synchronized (synchedList) {
// while the list is empty, wait
while (synchedList.isEmpty()) {
System.out.println("List is empty...");
synchedList.wait();
System.out.println("Waiting...");
String element = (String) synchedList.remove(0);
// method to add an element in the list
public void addElement(String element) {
System.out.println("Opening...");
synchronized (synchedList) {
// add an element and notify all that an element exists
synchedList.add(element);
System.out.println("New Element:'" + element + "'");
synchedList.notifyAll();
System.out.println("notifyAll called!");
System.out.println("Closing...");
public static void main(String[] args) {
final ObjectDemo demo = new ObjectDemo();
Runnable runA = new Runnable() {
public void run() {
String item = demo.removeElement();
System.out.println("" + item);
} catch (InterruptedException ix) {
System.out.println("Interrupted Exception!");
} catch (Exception x) {
System.out.println("Exception thrown.");
Runnable runB = new Runnable() {
// run adds an element in the list and starts the loop
public void run() {
demo.addElement("Hello!");
Thread threadA1 = new Thread(runA, "A");
threadA1.start();
Thread.sleep(500);
Thread threadA2 = new Thread(runA, "B");
threadA2.start();
Thread.sleep(500);
Thread threadB = new Thread(runB, "C");
threadB.start();
Thread.sleep(1000);
threadA1.interrupt();
threadA2.interrupt();
} catch (InterruptedException x) {
让我们来编译和运行上面的程序,这将产生以下结果:
List is empty...
List is empty...
Opening...
New Element:'Hello!'
notifyAll called!
Closing...
Waiting...
Waiting...
List is empty...
Interrupted Exception!

我要回帖

更多关于 华硕2017笔记本新品 的文章

 

随机推荐