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 ...
随机推荐
- Day5 函数递归,匿名、内置行数,模块和包,开发规范
一.递归与二分法 一.递归 1.递归调用的定义 递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身 2.递归分为两类:直接与间接 #直接 def func(): print('from fu ...
- SSM基础整合
1.表现层: 依赖jar包:spring+JSP+文件上传组件+dubbo+fastdfs web.xml配置:乱码过滤器+DispatcherServlet前端控制器 <!-- 配置post乱 ...
- MySQL 基础 简单操作
一.数据库基础 什么是数据库 数据库:保存有组织的数据的容器(通常是一个文件或一组文件). 表:是一种结构化的文件,可以用来存储数据(类似Excel表).数据库就是由成千上万个表组成. 什么事SQL ...
- [Java in NetBeans] Lesson 03. More Variables / Type Casting
这个课程的参考视频在youtube. 主要学到的知识点有: It is different from python, that "1" only present string &q ...
- VS中去掉空格虚点
Ctrl + R+W 可以在VS中添加或移除 空格虚点.
- leetcode 108
二分法建立二叉树,每次把左半部分作为左子树右半部分作为右子树,递归建立BST. #include<bits/stdc++.h> using namespace std; /** * Def ...
- !! zcl_TD 用法注释02 力攻(动能<4)
力攻(动能<4)创新高下M5可持有力攻(动能<4)不创新高下M5可减仓
- C\C++程序结束另外的进程
WinExec("taskkill /f /im center_flextrbo.exe",SW_HIDE);
- vm虚拟机出现Disk启动失败
https://jingyan.baidu.com/article/a501d80c0e45b8ec630f5ed6.html
- hdu4749 kmp改进
这题说的是给了一个模板串 然后又给了一个串 需要找出类似的按个模板串 , 改相等的位置要相等 该大于的位置到大于 我们将模板串做好失配指针就ok了,然后匹配和原来的匹配不同,这个匹配需要的是相对匹配, ...