接着上节的内容
,接下来我们就具体的来实现一下
,我们这个线程与线程之间的这种通信
,那么这种通信我们先来实现第1种
,就是我们通过synchronized
,这个关键字来对线程进行这个锁保护的
,那么这种情况下
,我们要实现线程与线程通信
,我们要借助于Object这个类里边的三个原生的本地方法
,那么这三个本地方法是wait notify notifyAll
,那么这三个方法首先你要了解到
,它们都是本地方法
,所谓本地方法就是这三个方法的具体实现
,它不是用Java来实现的
,它是虚拟机底层里边用C或者C++来实现
,就说这三个方法比较底层
,而且是final方法
,所以说这三个方法是不可以被重写
,这是我们要掌握的第一点
,那么第2点就这三个方法到底有什么用
,那么wait方法我们调用了它的话
,它的作用会阻塞当前线程
,相当于它让当前的线程释放掉
,这个线程拥有的同步锁
,然后让线程进入等待状态
,然后后续再去和其他线程
,后续再去和其他的线程一起去争这个同步锁
,所以说这里边是wait方法
,它的这个意义
,那么第3个
,我们notify这个方法
,notify这个方法它被调用的时候
,它会做一个事
,什么事
,去唤醒一个正在等待这个同步锁的这个线程
,就是说wait方法它把当前线程阻塞
,相当于把当前线程的锁给释放掉
,然后
,然后等待着去进入等待状态
,
然后等待去获取
,等待着下一次去获取的这把锁
,而notify这个方法
,它相当于在当前线程当中调用notify
,这方法相当于去唤醒别的正在等待这把锁的线程
,来抢这把锁
,就是说这里边是notify它的作用
,那么如果说我们有多个线程正在等待
,同意把这个线通过锁的时候
,这个方法它只能够唤醒其中一个线程
,它不能够唤醒所有线程
,这是notify这个方法的基本作用
,而第3个方法notifyAll这个方法
,作用基本上跟notify一致
,只不过说区别在于notify它只唤醒其中一个线程
,而notifyAll它会把所有等待这个同步锁的线程全部唤醒
,这就是这三个方法它的基本作用
,但这里边注意一点
,不管是notify还是notifyAll
,这两个方法
,只是起到唤醒等待同步锁的线程
,它并不决定由哪个线程来获得这把同步锁
,这一点也要注意
,那么也就是说它只起到一个呼唤的作用
,起到一个我告诉你这个可以过来抢同步锁了
,但是这个同步锁你抢不抢到
,还是我自己抢到
,还是你抢得到
,谁抢到同步锁
,这两个方法决定不了
,并不是说它唤醒谁
,谁就一定能拿到锁
,它唤醒谁
,只不过说是让这个线程有
,或有去抢这把锁的这个资格
,但是到底这个锁最终会被谁得到
,这两个方法它是决定不了的
,这点一定要注意
,好吧
,那么对于这几个东西有了一个基本的认识
,
那接下来我们就通过在代码层面
,来通过这个实战的代码案例
,然后让大家明白
,我们怎么样通过Object类那里边的这三个方法
,来实现这个线程交互的
,好吧
,这边我们怎么样去演示
,当然就是我们模拟实现一下
,生产者-消费者这个设计模式
,通过这个设计模式的程序的一个模拟实现
,来展现我们线程与线程交互
,那么这里边
,这里边什么呢
,来吧
,我们就直接上代码
,上代码了
,我们在这里边新建一个模块
,来这边新建一个Module
,这里边是Thtead
,然后7 然后Module
,好
,在这里边我们新建一个class类
,好
,cn.ybzy.demo.ThreadTest1
,那么在这里边
,这里边我们这是做测试的
,这里边我们是一会运行测试
,运行
,运行测试的主方法main方法
,好吧
,那这里边我就PSVM
,这边是这样子
,那下边首先
,首先这样子
,首先我要这一个类
,定义一个类
,定义一个定义
,定义一个类
,来模拟什么
,模拟
,我们的这个生产者与消费者的中间的起到一个缓冲作用的队列
,在生产者和消费者之间
,
之间的什么
,缓冲
,缓冲区
,缓冲区作用的这个队列
,缓冲区就叫缓冲区
,我们就模拟生产者与消费者之间的一个缓冲区
,好吧
,来我们这边定义个class
,一个class
,名字叫什么呢
,来
,我这里边叫
,我的笔记当中叫Valuobject
,好吧
,我就叫就Valuobject
,好
,定义这么一个
,生产者与消费者之间起到缓冲区作用的什么来着
,那个东西
,那个中间的这么一个东西
,那么在这里边我定义个
,我定义个啥 public static
,定义个静态的一个变量
,这个变量就字符串类型的变量
,String字符串类型变量
,然后这边就是value
,默认就让它等于空
,这个属性这个value里边
,这就是我们模拟的那个缓冲区
,模拟的缓冲区
,模拟缓冲区
,好
,接下来我们就是
,接下来什么
,接下来我们是模拟
,模拟
,或者实现
,实现这个生产者
,实现这个生产者的线程类 好吧
,来 我们这边来一个class
,它是什么呢
,又叫P
,然后我们继承Thread这个线程的父类
,好
,然后在这里边
,我们Insert@Override
,覆盖里边的run方法
,看见没有覆盖里边的run方法
,好吧
,这是生产者
,
模拟作为生产者的那条线程内
,好
,同样道理
,我们有生产者线程类是不是也有消费者线程类
,所以实现消费者线程类
,来了
,这个我把P改成什么
,consumer改成C
,那么两条线程类
,两个线程类
,生产者线程类里边 来 给它一个构造器
,叫public
,然后这边P给一个构造器
,做这个构造器干什么
,主要是我要一会用这个线程的时候
,我需要这个线程
,两条线程类
,它的这个用同一个这个锁对象
,所以这里边我要初始化一把锁进来
,这边就叫object lock
,等于什么呢
,就是
,就它了
,我这边叫private
,然后这个锁我要传过来
,用构造器的方式
,我要初始化这把锁对象
,好
,this.lock=lock
,搞定
,看到没有
,同样道理我的消费者里边也是一样
,比如说这是C
,看到没有
,这边生产者线程类消费者线程类
,而我在线程类里边线程的执行体里边做什么呢
,生产者
,生产者
,根据我们生产者-消费者那个模型
,那个模型
,我们在生产者里边做什么呢
,首先
,首先来
,首先我们搞一个while循环
,搞一个一直循环的一个死循环
,然后在循环里边
,我们把这个线程保护起来
,
来
,搞个while死循环true
,好 在这里边我们
,我们搞一个啥
,搞个try
,搞个try
,try里边
,try里边我们用这个synchronized关键字做一个
,做一个保护
,做一个保护
,来
,我们在这里边try catch
,Exception e
,这样子
,然后在try里边我们synchronized
,然后这里边这个锁
,作为锁的对象是哪个
,就是我的构造器初始化进来的lock
,看见没有
,初始化进来lock
,那么在这里边
,来作为生产者
,作为生产者的基本功能
,基本功能
,生产者的基本功能是什么
,生产数据
,生产数据
,生产者
,生产数据
,在这里边产生数据
,但是产生数据的话
,它不能够啥呢
,不能够直接产生
,因为
,因为它要判断
,判断什么东西
,判断它的缓冲区里面有没有东西
,如果说缓冲区是空的情况下
,它才去生产
,如果缓冲区已经满了
,缓冲区里边有值
,我生产者能生产吗
,生产者这个时候就不能生产
,而是什么
,而是通知消费者去把缓冲区里边的数据给我消费掉
,然后这边是这样的一个基本逻辑
,对不
,所以说首先生产者基本功能实现
,