线程通信

本文详细介绍了Java中线程间的通信机制,包括线程间如何通过共享对象进行通信、使用wait()、notify()及notifyAll()等方法实现线程间的等待与唤醒。此外,还讨论了如何避免丢失信号的问题,并提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考URL:Java并发性和多线程介绍

 

1.线程间通信,例如线程A通知线程B已经准备好了数据

2.通过共享对象通信,设置boolean值

3.忙等待,类似于偏向锁,等待然后自旋直到前一个线程执行结束

4.wait(),notify()和notifyAll()

以下是一个线程等待和唤醒的例子,doWait()等待,doNotify()唤醒。

public class MonitorObject{
}

public class MyWaitNotify{

  MonitorObject myMonitorObject = new MonitorObject();

  public void doWait(){
    synchronized(myMonitorObject){
      try{
        myMonitorObject.wait();// 先获得锁,再wait()
      } catch(InterruptedException e){...}
    }
  }

  public void doNotify(){
    synchronized(myMonitorObject){
      myMonitorObject.notify();
    }
  }
}

(1)一个线程调用了任意一个对象的wait就变为非运行状态,直到调用同一个对象的notify才进入就绪状态。

(2)线程必须在同步块里调用wait()或者notify(),为了获得对象的锁。这是强制性的!

(3)当一个线程调用一个对象的notify(),正在等待该对象的所有线程中将有一个线程被唤醒并允许执行,这个将被唤醒的线程是随机的,不可以指定唤醒哪个线程。

(4)一旦一个线程被唤醒,先要获取锁,然后才能wait()退出该线程。也就是说如果多个线程被notifyAll()唤醒,那么在同一时刻将只有一个线程可以退出wait()方法

5.丢失的信号:!!!

(1)如果一个线程先于被通知线程调用wait()前调用了notify(),等待的线程将错过这个信号。假如前一个线程先唤醒了,此时后一个线程还没来,那么当后一个线程来了的时候就会丢失前一个线程的信号量

(2)信号类包含了共享变量类和一个boolean信号

public class MyWaitNotify2{// 信号类

  MonitorObject myMonitorObject = new MonitorObject();// 共享对象
  boolean wasSignalled = false;// 信号
  
  public void doWait(){
    synchronized(myMonitorObject){
      // 防止假唤醒,用while 而不是if,为假的时候一直等待,直到为真,但是会消耗cpu性能,即一直自旋
      while(!wasSignalled){// 在wait前,先判断信号量为真
        try{
          myMonitorObject.wait();
         } catch(InterruptedException e){...}
      }
      wasSignalled = false;// 在wait后,设置信号量为假,表示自己没有被通知过,需要等待通知
    }
  }

  public void doNotify(){
    synchronized(myMonitorObject){
      wasSignalled = true;// 在notify前,设置信号量为假,表示已经被通知过
      myMonitorObject.notify();
    }
  }

}

6.不要在字符串常量或全局对象中调用wait(),应该使用唯一的对象

当有两个信号类的时候,jvm把它们用到的不同的字符串转换为同一个对象,会造成信号量丢失和伪唤醒问题。

假设AB线程为实例1的线程,CD线程为实例2的线程,两个实例的信号量分别保存在两个实例中,但是他们的对象是同一个。

AB线程结束后错误地唤醒了CD,即伪唤醒;或者AB等待的信号被CD收到,即信号丢失。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值