java使用wait(),notify(),notifyAll()实现等待/通知机制
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()实现等待/通知机制的更多相关文章
- Java并发编程,Condition的await和signal等待通知机制
Condition简介 Object类是Java中所有类的父类, 在线程间实现通信的往往会应用到Object的几个方法: wait(),wait(long timeout),wait(long tim ...
- Java 线程间通信 —— 等待 / 通知机制
本文部分摘自<Java 并发编程的艺术> volatile 和 synchronize 关键字 每个处于运行状态的线程,如果仅仅是孤立地运行,那么它产生的作用很小,如果多个线程能够相互配合 ...
- Java Concurrency - wait & notify, 等待通知机制
生产者消费者问题是一个常见的多线程同步案例:一组生产者线程和一组消费者线程共享一个初始状态为空.大小为 N 的缓冲区.只有当缓冲区没满的时候,生产者才能把消息放入缓冲区,否则必须等待:只有缓冲区不空的 ...
- Java多线程学习(四)等待/通知(wait/notify)机制
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader
1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- Java多线程之三volatile与等待通知机制示例
原子性,可见性与有序性 在多线程中,线程同步的时候一般需要考虑原子性,可见性与有序性 原子性 原子性定义:一个操作或者多个操作在执行过程中要么全部执行完成,要么全部都不执行,不存在执行一部分的情况. ...
- Java并发之等待/通知机制
目录 1 前言 1.1 先来段代码放松一下 2 Object wait()/notify() 2.1 一段入门代码 2.2 问题三连击 a.为什么官方说wait() 要放在while里面? b.为什么 ...
- 【Java并发基础】使用“等待—通知”机制优化死锁中占用且等待解决方案
前言 在前篇介绍死锁的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象. // 一次性申请转出账户和转入账户,直到成功 while(!actr.apply(this, targe ...
随机推荐
- mosquitto SSL认证
[11]MQTT mosquitto 双向SSL认证配置方式 [12]MQTT mosquitto 单向SSL认证的配置方式 Mosquitto服务器的搭建以及SSL/TLS安全通信配置(比较可信) ...
- ASP.Net中的四种状态保持机制
每个人上网可多有过这样的情况,当我们登陆某个网站时,在登陆的旁边会有一个 "记住我" 的复选框,有的网站还会让用户选择记住我.这个记住我是怎么实现的呢? 其实就用利用的是cooki ...
- CLR总览
Contents 第1章CLR的执行模型... 4 1.1将源代码编译成托管代码模块... 4 1.2 将托管模块合并成程序集... 6 1.3加载公共语言运行时... 7 1.4执行程序集的代码.. ...
- git-代码同步至github
代码同步到github上 Last login: Wed Mar 27 13:53:06 on ttys001localhost:~ ligaijiang$ gitusage: git [--vers ...
- Selenium基础知识(三)元素判断
一.由于有些页面加载完后,某些元素还没有加载,这样就会导致异常,脚本稳定性变差 为了解决这个问题,selenium提供了WebDriverWait以及implicitly_wait()等待 WebDr ...
- vue中使用kindeditor富文本编辑器
1.去官网下载kindeditor 2.将其放在一个名为kindeditor的文件夹里,并且将它放在vue里的static文件夹下 3.创建kindeditor.vue <template> ...
- jQuery-手风琴伸缩效果
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- centos安装java的jdk
1.下载 jdk-8u101-linux-x64.rpm http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads- ...
- ReentrantLock源码(二)
一.ReentrantLock类中的方法解读. 1.lock方法.实现了接口Lock中的lock方法.这里实际上是调用了sync成员变量的lock方法来实现.所以取决于sync的实现. 2.unloc ...
- anconda1.8+cuda9.0+cudnn7.0.5+tensorflow1.7(win10)安装
1.下载安装cuda9.0 https://developer.nvidia.com/cuda-90-download-archive 2.下载cudnn7.0.5,下载cuda9.0的对应版本 ht ...