notifyall如何在 Java 中正确使用 wait,notify 和 notifyAll

notifyall  时间:2021-06-10  阅读:()

在Java根类java.lang.Object中包含了3个重载的wait()方法以及 notify()方法和notifyAll()

wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。

wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。

wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

notify() 唤醒在此对象监视器上等待的单个线程。

notifyAll() 唤醒在此对象监视器上等待的所有线程。

object类的六个方法都有什么?分别是什么意思?有什么用途?

protected Object clone() 创建并返回此对象的一个副本。

boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。

protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

Class getClass() 返回此 Object 的运行时类。

int hashCode() 返回该对象的哈希码值。

void notify() 唤醒在此对象监视器上等待的单个线程。

void notifyAll() 唤醒在此对象监视器上等待的所有线程。

String toString() 返回该对象的字符串表示。

void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。

void wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导

IllegalArgumentException是什么错误

代码太乱了没怎么看 做级联操作的话,不需要一次性将5个下拉框都填充值,只需要填充第一级下拉框,然后触发第一级下拉框的onChange事件时通过dwr获取第二级下拉框的数据,以此类推. 以上的报错信息是方法的传参有问题,你可能传了一个null到后台,你可以debug一下后台的获取数据的方法,看看是哪个参数有问题.

在什么地方wait()方法、notify()及notifyAll()方法可以被使用?

比如:生产者和消费者共同来操作堆栈吧,消费者从堆中取产品,生产者放产品! 只有当生产者把产品放到了堆中,消费者才可以取到产品,不然就会出错! 当你用两个线程来分别控制生产者和消费者时.他们是同时的. 你可以用wait()方法让消费者那个线程停下来等生产者把产品放到堆里,放完之后,消费者才可以取. 当生产者放完了产品之后,就用notify()通知wait(),让消费者获得运行的权利! 希望悄能听清楚了!?呵呵!

如何在 Java 中正确使用 wait,notify 和 notifyAll

wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。

本文对这些关键字的使用进行了描述。

在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。



举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓 冲区中有内容待消费(不为空)。

相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。

我们可以利用wait()来让一个线程在某些条件下暂停运行。

例如,在生产者消费者模型中,生产者线程在缓冲区为满的时候,消费者在缓冲区为空的时 候,都应该暂停运行。

如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待中的线程重新开始运行。

不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。

换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。

但如果多个线程在等待这个信 号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。

在这篇文章中你将会学到如何使用 wait、notify 和 notifyAll 来实现线程间的通信,从而解决生产者消费者问题。

如果你想要更深入地学习Java中的多线程同步问题,我强烈推荐阅读Brian Goetz所著的《Java Concurrency in Practice | Java 并发实践》,不读这本书你的 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!我会推荐阅读《Effective Java》,这是关于如何正确使用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都是使用在同一个共享对象上的。

炭云188元/年,上海CN2 VPS/2核/384MB内存/8GB空间/800GB流量/77Mbps端口/共享IP

炭云怎么样?炭云(之前的碳云),国人商家,正规公司(哈尔滨桓林信息技术有限公司),主机之家测评介绍过多次。现在上海CN2共享IP的VPS有一款特价,上海cn2 vps,2核/384MB内存/8GB空间/800GB流量/77Mbps端口/共享IP/Hyper-v,188元/年,特别适合电信网络。有需要的可以关注一下。点击进入:炭云官方网站地址炭云vps套餐:套餐cpu内存硬盘流量/带宽ip价格购买上...

atcloud:480G超高防御VPS低至$4/月,美国/新加坡等6机房,512m内存/1核/500g硬盘/不限流量

atcloud主要提供常规cloud(VPS)和storage(大硬盘存储)系列VPS,其数据中心分布在美国(俄勒冈、弗吉尼亚)、加拿大、英国、法国、德国、新加坡,所有VPS默认提供480Gbps的超高DDoS防御+不限流量,杜绝DDoS攻击骚扰,比较适合海外建站等相关业务。ATCLOUD.NET是一家成立于2020年的海外主机商,主要提供KVM架构的VPS产品、LXC容器化产品、权威DNS智能解...

HyperVMart:加拿大vps,2核/3G/25G NVMe/G口不限流量/季付$10.97,免费Windows系统

hypervmart怎么样?hypervmart是一家成立了很多年的英国主机商家,上一次分享他家还是在2年前,商家销售虚拟主机、独立服务器和VPS,VPS采用Hyper-V虚拟架构,这一点从他家的域名上也可以看出来。目前商家针对VPS有一个75折的优惠,而且VPS显示的地区为加拿大,但是商家提供的测速地址为荷兰和英国,他家的优势就是给到G口不限流量,硬盘为NVMe固态硬盘,这个配置用来跑跑数据非常...

notifyall为你推荐
tde如何区别动作数据与模型的种类。tde tda lat 啊? mmdat89s52单片机AT89S52单片机和AT89C51单片机的区别搜索引擎的概念什么叫搜索引擎?搜索引擎的类型有哪些?自定义表情QQ自定义表情js后退多级页面间的后退如何实现(js方法)模式识别算法模式识别的简史印度尼西亚国家代码国际代码kjavaKJAVA业务信息费是什么东西啊,我怎么会被莫莫名其妙的扣掉11元啊维基百科中文网站科普网页最大的谁有移动硬盘文件或目录损坏且无法读取移动硬盘提示文件或目录损坏且无法读取,怎么修复
荷兰服务器 liquidweb 我爱水煮鱼 免费mysql 河南移动邮件系统 双线主机 域名和空间 免费美国空间 卡巴斯基破解版 东莞服务器 爱奇艺会员免费试用 中国电信宽带测速器 cloudlink 空间登录首页 www789 百度云加速 电信网络测速器 浙江服务器 注册阿里云邮箱 亿库 更多