java 线程等待通知_Java 线程间通信 —— 等待 / 通知机制

本文部分摘自《Java 并发编程的艺术》

volatile 和 synchronize 关键字

每个处于运行状态的线程,如果仅仅是孤立地运行,那么它产生的作用很小,如果多个线程能够相互配合完成工作,则将带来更大的价值

Java 支持多个线程同时访问一个对象或者对象的成员变量,使用 volatile 关键字可以保证被修饰变量的可见性,意味着任一线程对该变量的任何修改,其他线程都可以立即感知到

synchronize 关键字可以修饰方法或者同步块,它主要确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性。synchronize 关键字的实现,本质是对一个对象的监视器(monitor)进行获取,而这个获取过程是排他的,也就是同一时刻只能有一个线程获取到由 synchronize 所保护对象的监视器

任何一个对象都拥有自己的监视器,任意一个线程对 Object 的访问(Object 由 synchronize 保护)的访问,首先要获得 Object 的监视器。如果获取失败,线程进入同步队列,线程状态变为 BLOCKED。当访问 Object 的前驱(获得了锁的线程)释放了锁,则该释放操作将唤醒阻塞在同步队列中的线程,使其重新尝试获取监视器

bf5e1b529363001869dd25a6c45ab7a5.png

等待 - 通知机制

一个线程修改了一个对象的值,另一个线程感知到变化,然后进行相应的操作,前者是生产者,后者是消费者,这种通信方式实现了解耦,更具伸缩性。在 Java 中为了实现类似的功能,我们可以让消费者线程不断地循环检查变量是否符合预期,条件满足则退出循环,从而完成消费者的工作

while(value != desire) { Thread.sleep(1000);}doSomething();

睡眠一段时间的目的是防止过快的无效尝试,这种实现方式看似能满足需求,但存在两个问题:

难以确保及时性

如果睡眠时间太长,就难以及时发现条件已经变化

难以降低开销

如果降低睡眠时间,又会消耗更多的处理器资源

使用 Java 提供了内置的等待 - 通知机制能够很好地解决上述问题,等待 - 通知的相关方法是任意 Java 对象都具备的

方法名称

描述

notify()

通知一个在对象上等待的线程,使其从 wait() 方法返回,返回的前提是该线程获取到了对象的锁

notifyAll()

通知所有等待在该对象上的线程

wait()

调用该方法的线程进入 WAITING 状态,只有等待另外的线程通知或被中断才返回,调用此方法会释放对象的锁

wait(long)

超时等待一段时间,参数时间是毫秒

wait(long, int)

对于超时时间更细粒度的控制,可以达到纳秒

等待 - 通知机制,是指一个线程 A 调用了对象 O 的 wait() 方法进入等待状态,而另一个线程 B 调用了对象 O 的 notify() 或者 notifyAll() 方法,线程 A 收到通知后从对象 O 的 wait() 方法返回,进而执行后续操作。上述两个线程通过对象 O 来完成交互,而对象上的 wait() 和 notify/notifyAll() 的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作

下述例子中,创建两个线程 WaitThread 和 NotifyThread,前者检查 flag 值是否为 false,如果符合要求,进行后续操作,否则在 lock 上等待,后者在睡眠一段时间后对 lock 进行通知

public class WaitNotify { static boolean flag = true; static Object lock = new Object(); public static void main(String[] args) throws InterruptedException { Thread waitThread = new Thread(new Wait(), "WaitThread"); waitThread.start(); TimeUnit.SECONDS.sleep(1); Thread notifyThread = new Thread(new Notify(), "NotifyThread"); notifyThread.........

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值