今天是我自学Java的第34天。
感谢你的观看,谢谢你。
话不多说,开始今天的学习:。
首先回顾下线程同步:
线程同步其实讲的就是线程之间的竞争。
通俗一点说就是:对于同一个任务,因为Java虚拟机的抢占式调度,线程一、线程二都抢着做,线程一还没做完,线程二就跑进来横插一脚,说白了不就好比两个人在互相竞争么?
对于这种情况,我们采用了同步机制来解决,让它们一次只能执行一个线程:线程一执行完,线程二才能进去。
那么现在问题来了:
线程之间既然有竞争,那有没有合作呢?
答案是有的,有竞争自然也会有合作。
用一个案例来说明:
刘小爱是个吃货,要去包子铺吃包子。
现有一个设定:刘小爱1次只能吃1个包子,包子铺1次只能生产1个包子,一有包子刘小爱就吃,吃完后,包子铺就开始生产,包子一生产出来,刘小爱就继续吃……
先不管符不符合现实逻辑哈,反正设定是这样的。
面对这个问题,该怎么办?
刘小爱是一个线程,包子铺也是一个线程,它们会操作同一个对象,也就是包子。
一、包子类
创建一个包子类,代码如下:
①包子类里面有一个属性叫isHave。
isHave用于判断是否有包子:如果为true,表示有包子;如果为false,表示没有包子。
②get/set方法用于获取和修改isHave属性。
其中默认有一个无参构造方法,可以省略不写。
二、刘小爱
创建一个刘小爱类,以实现Runnable接口的方法来创建刘小爱线程:
①刘小爱类中有一个包子对象。
②设定构造方法(baozi)。
同时重写run方法,设定一个while死循环,毕竟有包子的话刘小爱就会不停地吃。
③锁对象:保证对象唯一。
因为刘小爱在吃包子的时候,包子铺不能进来干涉,这是一开始的设定,所以需要设定一个锁。
④if判断语句:如果为真,表示有包子。
那么刘小爱就吃包子,并打印输出。
⑤setIsHave方法和notify()方法:
setIsHave方法:刘小爱将包子吃完了,包子没了,将isHave设定为false。
notify方法是Object类里的一个方法,Obeject是所有类的顶层父类,也就是说所有对象都自带这个方法。
notify方法:唤醒此对象监视器上的其他未进来的线程。
什么意思呢?就是将另一个线程(也就是包子铺线程)唤醒。
⑥if判断语句:如果不为真,表示没有包子。
没有包子,刘小爱就等包子生产好了再吃,进入等待状态。
wait方法和notify方法一样,也是Object类里的一个方法。
wait方法:一个线程进行了规定操作后,就进入等待状态。
三、包子铺
创建一个包子铺类,以实现Runnable接口的方法来创建包子铺线程:
①包子铺中有个baozi对象。
其中设定好构造方法(baozi),并且和刘小爱一样,重写run方法,while死循环。
②锁对象:保证对象唯一。
同样的,包子铺在生产包子的时候,刘小爱不能进来,所以要锁对象。
③if判断语句:如果为真,表示有包子。
那么包子铺要等待包子被吃完,故使用wait方法。
④if判断语句:如果不为真,表示没有包子。
那么包子铺要生产包子,并打印输出。
⑤setIsHave方法和notify方法:
现在包子铺生产好包子了,那么包子铺要将isHave设定为true,并将刘小爱唤醒。
四、测试
现在类都创建好了,开始测试:
①创建包子对象。
②创建刘小爱和包子铺对象。
用包子对象给他们初始化赋值,注意要保证它们为同一个包子对象。
③创建两个线程。
分别给线程初始化赋值:一个为包子铺线程,一个为刘小爱线程。
④将这两个线程启动。
现在代码都写好了,最后看看代码执行后的效果:
包子铺生产包子,刘小爱吃包子,两个线程互相合作依次进行。
以上就是刘小爱去包子铺吃包子的案例。
这个案例对应了Java线程中的生产者消费者模式,该例子在逻辑上并不算太缜密,不过相对而言更好理解。
生产者对应谁?
包子铺在生产包子,自然它就是生产者;
消费者对应谁?
刘小爱在吃包子,自然它就是消费者。
生产者消费者模式在面试中有可能会被面试官问到,所以最好要将其理解,不过不要说什么刘小爱去包子铺吃包子的案例,面试官听不懂的。
面试官可不知道什么包子铺,更不知道什么刘小爱,要说生产者和消费者。
总结:
本文分享自微信公众号 - 刘小爱(liuxiaoai946)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4569917/blog/4451318