1. public class WaitNotify {
  2. static boolean flag=true;
  3. static Object lock=new Object();
  4.  
  5. static class Wait implements Runnable{
  6. @Override
  7. public void run() {
  8. synchronized (lock){
  9. while(flag){
  10. try{
  11. System.out.println(Thread.currentThread()+" flag is true. wait " +
  12. "@ "+new SimpleDateFormat("HH:mm:ss").format(new Date()));
  13. lock.wait();
  14. }catch (InterruptedException e){
  15. }
  16. }
  17. }
  18. System.out.println(Thread.currentThread()+" flag is false.running " +
  19. "@"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
  20.  
  21. }
  22. }
  23.  
  24. static class Notify implements Runnable{
  25. @Override
  26. public void run() {
  27. synchronized (lock) {
  28. System.out.println(Thread.currentThread() + " hold lock. notify " +
  29. "@ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
  30. lock.notifyAll();
  31. flag = false;
  32. SleepUtils.second(5);
  33. }
  34. synchronized (lock){
  35. System.out.println(String.format(Thread.currentThread() + " hold lock again. sleep " +
  36. "@" + new SimpleDateFormat("HH:mm:ss").format(new Date())));
  37. SleepUtils.second(5);
  38. }
  39. }
  40. }
  41.  
  42. public static void main(String[] args) {
  43. Thread waitThread=new Thread(new Wait(),"WaitThread");
  44. waitThread.start();
  45. try {
  46. TimeUnit.SECONDS.sleep(1);
  47. }catch (InterruptedException e){
  48.  
  49. }
  50. Thread notifyThread=new Thread(new Notify(),"NotifyThread");
  51. notifyThread.start();
  52. }
  53. }

程序执行结果:

  1. Thread[WaitThread,5,main] flag is true. wait @ 14:41:12
  2. Thread[NotifyThread,5,main] hold lock. notify @ 14:41:13
  3. Thread[NotifyThread,5,main] hold lock again. sleep @14:41:18
  4. Thread[WaitThread,5,main] flag is false.running @14:41:23

1.使用wait(),notify(),notifyAll()方法之前,要获取同一个对象的锁。

2.调用wait()方法之后,线程会从RUNABLE状态变为WAITING状态,并会释放对象锁,并会将线程移入到对象的等待队列中。

3.notify()和notifyAll()调用之后,等待的线程的wait方法并不会立马返回,需要锁空闲的时候,等待的线程获取了锁,wait()方法才会返回。

4.调用了notify()和notifyAll()方法之后,notify会将一个线程从等待队列放置到同步队列,同步队列是因为锁被占有而处于BLOCKED阶段的线程,notifyAll则是将等待队列中所有的线程都移动到同步队列,这两个方法都是将线程从WAITING状态变为BLOCKED状态。

5.从wait方法返回的条件是获得了调用对象的锁。

该程序的执行流程是首先WaitThread获取了lock,然后waitThread调用wait方法,会释放锁,并将锁移入等待队列,接着notifyThread会获取锁,调用notifyAll,但是wait()方法并没有返回,因为lock没有释放,notifyThread会睡眠5秒,这时同步队列中有两个线程要获取lock,一个是notifyThread,一个是WaitThread,结果显示是notifyThread又重新获取了锁,所以这时的wait方法依然不能返回,当notifyThread执行完了之后,释放锁,waitThread获取了锁,并且wait方法返回,waitThread执行完成。

java等待/通知经典模式

等待方:

1)获取对象锁

2)如果条件不满足,那么就调用对象的wait()方法,被通知后依然要检查条件

3)条件满足则执行相应逻辑

对应的伪代码:

  1. synchronized(对象){
  2. while(条件不满足){
  3. 对象.wait()
  4. }
  5. 执行对应逻辑代码
  6. }

通知方:

1)获取对象锁

2)改变条件

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

对应的伪代码:

  1. synchronized(对象){
  2. 改变对象条件
  3. 对象.notifyAll()
  4. }

 

java中的Thread.join()方法使用了等待/通知经典范式

java中的Thread.join()也算是线程通信的一种方式,表示挂起当前线程,执行子线程,等到子线程执行完成之后再返回。join()方法还提供了两个超时方法,如果子线程在规定时间没有终止,就会从join()方法中返回。

Thread.join()方法源代码:

  1. //join函数的超时方法
      public final synchronized void join(long millis)
  2. throws InterruptedException {
  3. long base = System.currentTimeMillis();
  4. long now = 0;
        
         //如果设置的超时时间小于0,抛出异常
  5. if (millis < 0) {
  6. throw new IllegalArgumentException("timeout value is negative");
  7. }

  8.      //调用wait()的时候采用delay
  9. if (millis == 0) {
  10. while (isAlive()) {
  11. wait(0);
  12. }
  13. } else {
  14. while (isAlive()) {
  15. long delay = millis - now;
  16. if (delay <= 0) {
  17. break;
  18. }
  19. wait(delay);
  20. now = System.currentTimeMillis() - base;
  21. }
  22. }
  23. }
  24.  
  25. public final synchronized void join(long millis, int nanos)
  26. throws InterruptedException {
  27.  
  28. if (millis < 0) {
  29. throw new IllegalArgumentException("timeout value is negative");
  30. }
  31.  
  32. if (nanos < 0 || nanos > 999999) {
  33. throw new IllegalArgumentException(
  34. "nanosecond timeout value out of range");
  35. }
  36.  
  37. if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  38. millis++;
  39. }
  40.  
  41. join(millis);
  42. }
  43.  
  44. public final void join() throws InterruptedException {
  45. join(0);
  46. }

子线程执行完成之后会调用子线程的notifyAll(),会通知所有等待在该线程对象上的方法。

java使用wait(),notify(),notifyAll()实现等待/通知机制的更多相关文章

  1. Java并发编程,Condition的await和signal等待通知机制

    Condition简介 Object类是Java中所有类的父类, 在线程间实现通信的往往会应用到Object的几个方法: wait(),wait(long timeout),wait(long tim ...

  2. Java 线程间通信 —— 等待 / 通知机制

    本文部分摘自<Java 并发编程的艺术> volatile 和 synchronize 关键字 每个处于运行状态的线程,如果仅仅是孤立地运行,那么它产生的作用很小,如果多个线程能够相互配合 ...

  3. Java Concurrency - wait & notify, 等待通知机制

    生产者消费者问题是一个常见的多线程同步案例:一组生产者线程和一组消费者线程共享一个初始状态为空.大小为 N 的缓冲区.只有当缓冲区没满的时候,生产者才能把消息放入缓冲区,否则必须等待:只有缓冲区不空的 ...

  4. Java多线程学习(四)等待/通知(wait/notify)机制

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  5. java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader

    1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...

  6. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  7. Java多线程之三volatile与等待通知机制示例

    原子性,可见性与有序性 在多线程中,线程同步的时候一般需要考虑原子性,可见性与有序性 原子性 原子性定义:一个操作或者多个操作在执行过程中要么全部执行完成,要么全部都不执行,不存在执行一部分的情况. ...

  8. Java并发之等待/通知机制

    目录 1 前言 1.1 先来段代码放松一下 2 Object wait()/notify() 2.1 一段入门代码 2.2 问题三连击 a.为什么官方说wait() 要放在while里面? b.为什么 ...

  9. 【Java并发基础】使用“等待—通知”机制优化死锁中占用且等待解决方案

    前言 在前篇介绍死锁的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象. // 一次性申请转出账户和转入账户,直到成功 while(!actr.apply(this, targe ...

随机推荐

  1. left join不同写法导致数据差异

    select m.*, p.specification, p.sales_price, p.promotion_price from product_detail p left join PRODUC ...

  2. 3.C#的访问权限修饰符

    C#里类及类成员的修饰符有以下五个如下:public 公开 类及类成员的修饰符 对访问成员没有级别限制private 私有 类成员的修饰符 只能在类的内部访问protected 受保护的 类成员的修饰 ...

  3. Jmeter安装与配置

    Jmeter下载与安装配置 1.下载地址:https://jmeter.apache.org/ Apache Jmeter首页,点击 Download Releases  然后,选择,安装版本,有li ...

  4. Deeplab v3+的结构代码简要分析

    添加了解码模块来重构精确的图像物体边界.对比如图 deeplab v3+采用了与deeplab v3类似的多尺度带洞卷积结构ASPP,然后通过上采样,以及与不同卷积层相拼接,最终经过卷积以及上采样得到 ...

  5. HDU 4565 So Easy(矩阵解公式)

    So Easy [题目链接]So Easy [题目类型]矩阵解公式 &题解: 感觉这种类型的题都是一个套路,这题和hdu 2256就几乎是一样的. 所以最后2Xn就是答案 [时间复杂度]\(O ...

  6. python --- 字符编码学习小结

    上半年的KPI,是用python做一个测试桩系统,现在系统框架基本也差不多定下来了.里面有用到新学的工厂设计模式以及以及常用的大牛写框架的业务逻辑和python小技巧.发现之前自己写的代码还是面向过程 ...

  7. 软件常用设置(VC, eclipse ,nodejs)---自己备用

    留存复制使用 1.VC ----1.1VC项目设置 输出目录: $(SolutionDir)../bin/$(platform)/$(Configuration) $(ProjectDir)../bi ...

  8. Rpgmakermv(15) PH任务插件

    插件介绍 一个用来简单显示任务阶段的任务书 使用方法 插件安装 下载js文件放置到游戏目录/plugins目录下.打开插件管理器,选择PH_QuestBook.js并开启. 插件参数 Show in ...

  9. Yii Restful api自定义字段

  10. Latex数学公式中的空格

    http://blog.sina.com.cn/s/blog_4ddef8f80100iwwv.html 两个quad空格 a \qquad b 两个m的宽度 quad空格 a \quad b 一个m ...