Java多线程
设计一个典型的场景,来阐述wait()、notify()、notifyAll(),生产消费者。
有生产者、消费者、缓冲队列(size=10)。
生产者不停地向缓冲队列里放数据,一旦队列满了,则wait(),并notify()消费者进行处理。
消费者不停地从缓冲队列里取数据,一旦队列空了,则wait(),并notify()生产者继续放数据。
生产者:
如果有想学习java的程序员,可来我们的java学习扣qun:94311,1692免费送java的视频教程噢!我整理了一份适合18年学习的java干货,送给每一位想学的小伙伴,并且每天晚上8点还会在群内直播讲解Java知识,欢迎大家前来学习哦。
生产者
notifyAll()放在A处,代表缓冲队列满了,再提醒消费者处理。
放在B处,代表只要缓冲队列里有数据,就提醒消费者处理。
消费者:
消费者
notifyAll()放在A处,代表缓冲队列空了,再提醒生产者放数据。
放在B处,代表只要处理了缓冲队列里的一个数据,就提醒生产者放数据。
测试类:
测试类
先解释一下notify()和notifyAll()。从字面意义上也很好理解,这两个都是用来唤醒wait()的线程,如果有多个线程wait(),notify()只唤醒其中一个,是哪一个就看JVM了。notifyAll()则唤醒所有wait()的线程,至于哪一个能拿到锁并执行,就看JVM了。
举个例子,有10个要吃饭的人都在睡觉(wait),我是送饭的人,我随机叫醒其中一个来吃饭,这是notify。我大喊一声“吃饭啦”,10个人全起来抢饭,这是notifyAll,至于是哪一个能抢到,就看命了。
使用wait、notify、notifyAll要注意的点:
1、 必须在synchronized里使用。
2、 必须在while而非if内使用wait。这是为了线程在被唤醒的前后都会去检查条件是否被满足。以刚才吃饭为例,有两个要吃饭的人,没饭吃就睡觉,有饭吃就被唤醒,然后都去领饭吃。但是在唤醒之后,吃之前要检查一下是否真的有饭,多线程情况下,可能唯一一碗饭被别人抢先拿走了,这时候本应去睡觉,但如果不做检查的话,就会一直去要吃的,从而产生错误。
3、 在多线程要处理的公共对象(数据)那里用wait,在本文,就是缓冲队列。
4、 如果是真多线程,比如多个生产者,多个消费者,用notifyAll更合适。
网友评论