public class WaitNotify {
static boolean flag=true;
static Object lock=new Object(); static class Wait implements Runnable{
@Override
public void run() {
synchronized (lock){
while(flag){
try{
System.out.println(Thread.currentThread()+" flag is true. wait " +
"@ "+new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
}catch (InterruptedException e){
}
}
}
System.out.println(Thread.currentThread()+" flag is false.running " +
"@"+new SimpleDateFormat("HH:mm:ss").format(new Date())); }
} static class Notify implements Runnable{
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock. notify " +
"@ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag = false;
SleepUtils.second(5);
}
synchronized (lock){
System.out.println(String.format(Thread.currentThread() + " hold lock again. sleep " +
"@" + new SimpleDateFormat("HH:mm:ss").format(new Date())));
SleepUtils.second(5);
}
}
} public static void main(String[] args) {
Thread waitThread=new Thread(new Wait(),"WaitThread");
waitThread.start();
try {
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){ }
Thread notifyThread=new Thread(new Notify(),"NotifyThread");
notifyThread.start();
}
}

程序执行结果:

Thread[WaitThread,5,main] flag is true. wait @ 14:41:12
Thread[NotifyThread,5,main] hold lock. notify @ 14:41:13
Thread[NotifyThread,5,main] hold lock again. sleep @14:41:18
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)条件满足则执行相应逻辑

对应的伪代码:

synchronized(对象){
while(条件不满足){
对象.wait()
}
执行对应逻辑代码
}

通知方:

1)获取对象锁

2)改变条件

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

对应的伪代码:

synchronized(对象){
改变对象条件
对象.notifyAll()
}

 

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

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

Thread.join()方法源代码:

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

     //调用wait()的时候采用delay
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
} public final synchronized void join(long millis, int nanos)
throws InterruptedException { if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
} if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
} if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
} join(millis);
} public final void join() throws InterruptedException {
join(0);
}

子线程执行完成之后会调用子线程的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. leetcode的注意点

    读懂一个题其实非常非常重要,读懂题包括要读懂题的问题是什么,条件是什么,考察的是什么知识点.所以能够读懂题就已经成功一半了,但是如果没有读懂题目就开始答题,就不假思索地乱写答案,那么会事倍功半,还得返 ...

  2. js并归排序的思路

    并归排序,就是分而治之,将长的数组分解为短的数组,一直分到最后,单个单个数组,我们就认为,只有一个元素的数组是有序的.然后再逐个的合并 1.拆分: 很容易 例如数组  [ 2,4,3,5,1,6,8, ...

  3. Stephen Wolfram自述

    Stephen Wolfram自述   作者: 阮一峰 大家听说过Stephen Wolfram(斯蒂芬·沃尔夫勒姆)吗? 了解他的经历和成就吗? 我对他了解不多,但是读了下面这篇2005年的演讲,联 ...

  4. winhex模版

    模版数据类型: char 字符 字符数组 char[i] binary  显示为二进制 hexadecimal uint32  显示4个字节,按16进制小端显示

  5. react-redux 使用后台数据初始化(渲染)界面

    注:首先在redux中改变state只能通过action操作,reducers改变state 在组件中 store.js import { createStore } from "redux ...

  6. hive-drop-import-delims选项对oracle的clob无效

    工作过程中发现了用sqoop将oracle中的数据导入到hive时,会因为oracle中类型为clob的字段中存在换行时,会造成hive的数据错位.即使加上了 --hive-drop-import-d ...

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

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

  8. 学习笔记<1>技术体系结构

    Android的系统架构采用了分层架构的思想,如上图所示.从上层到底层共包括四层,分别是   1.应用程序程序层   2.应用框架层   3.系统库和Android运行时 4.Linux内核.   每 ...

  9. C#深入研究ArrayList动态数组自动扩容原理

    1 void Test1() { ArrayList arrayList = new ArrayList(); ; ; i < length; i++) { arrayList.Add(&quo ...

  10. hdu5293 lca+dp+树状数组+时间戳

    题意是给了 n 个点的树,会有m条链条 链接两个点,计算出他们没有公共点的最大价值,  公共点时这样计算的只要在他们 lca 这条链上有公共点的就说明他们相交 dp[i]为这个点包含的子树所能得到的最 ...