java线程的等待、通知机制【读书笔记】
代码示例:
package com.baidu.nuomi.concurrent; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; /**
* Created by sonofelice on 16/6/18.
*/
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object(); public static void main(String[] args) throws Exception{
Thread waitThread = new Thread(new Wait(),"WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);
Thread notifyThread = new Thread(new Notify(),"NotifyThread");
notifyThread.start(); }
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(Thread.currentThread() + "hold lock again. sleep @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
SleepUtils.second(5);
}
}
}
}
输出如下:
Thread[WaitThread,5,main] flag is true. wait @ 12:21:04
Thread[NotifyThread,5,main]hold lock. notify @ 12:21:05
Thread[NotifyThread,5,main]hold lock again. sleep @ 12:21:10
Thread[WaitThread,5,main]flag is false. running @ 12:21:15 Process finished with exit code 0
调用wait() notify() notifyAll()方法时需要注意的细节:
1)使用wait() notify() notifyAll() 时需要先对调用对象加锁;
2)调用wait()方法后,线程状态由RUNNING 变为WAITING,并将当前线程放置到对象的等待队列。
3)notify()或notifyAll() 方法调用后,等待线程依旧不会从wait返回,需要调用notify()或notifyAll()的线程释放锁之后,等待线程才有机会从wait()返回。
4)notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而notifyAll()方法则是将等待队列中的所有的线程全部移到同步队列,被移动的线程状态由WAITING变为BLOCKED。
5)从wait()方法返回的前提是获得了调用对象的锁。
从上面的细节可以看出,等待/通知机制依托于同步机制,其目的就是确保等待线程从wait()方法返回时能够感知到通知线程对变量做出的修改。
从而抽象出等待/通知的经典范式:
等待方:
1)获取对象锁;
2)如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
3)条件满足则执行对应的逻辑。
对应的伪代码如下:
synchronized(对象){
while(条件不满足){
Object.wait();
}
逻辑处理
}
通知方:
1)获得对象的锁;
2)改变条件;
3)通知所有等待在对象上的线程。
对应的伪代码如下:
synchronized(对象){
改变条件
对象.notifyAll();
}
java线程的等待、通知机制【读书笔记】的更多相关文章
- java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader
1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...
- 一 java线程的等待/通知模型
java 中线程之间的通信问题,有这么一个模型:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程.前者是生产者,后者就是消费者 ...
- Java并发之等待/通知机制
目录 1 前言 1.1 先来段代码放松一下 2 Object wait()/notify() 2.1 一段入门代码 2.2 问题三连击 a.为什么官方说wait() 要放在while里面? b.为什么 ...
- 二 Java利用等待/通知机制实现一个线程池
接着上一篇博客的 一Java线程的等待/通知模型 ,没有看过的建议先看一下.下面我们用等待通知机制来实现一个线程池 线程的任务就以打印一行文本来模拟耗时的任务.主要代码如下: 1 定义一个任务的接口 ...
- Java并发编程(04):线程间通信,等待/通知机制
本文源码:GitHub·点这里 || GitEE·点这里 一.概念简介 1.线程通信 在操作系统中,线程是个独立的个体,但是在线程执行过程中,如果处理同一个业务逻辑,可能会产生资源争抢,导致并发问题, ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- 【Java并发基础】使用“等待—通知”机制优化死锁中占用且等待解决方案
前言 在前篇介绍死锁的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象. // 一次性申请转出账户和转入账户,直到成功 while(!actr.apply(this, targe ...
- Java并发读书笔记:线程通信之等待通知机制
目录 synchronized 与 volatile 等待/通知机制 等待 通知 面试常问的几个问题 sleep方法和wait方法的区别 关于放弃对象监视器 在并发编程中,保证线程同步,从而实现线程之 ...
- 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析
不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08 ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...
随机推荐
- SpringMVC+RestFul详细示例实战教程
一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...
- SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)
由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件 ...
- 私有云存储搭建(owncloud)
第一步.搭建LAMP(基于linux7.1.1503) 1 配置yum(网络加本地,下面为网络) [vault.centos.org_7.1.1503_os_x86_64_] name=added f ...
- 编程练习------C/C++分别实现字符串与整数的转换
C/C++分别实现字符串与整数的转换 前提:不使用 itoa 和 atoi. 方法一.C和C++通用的一种转换手段是: 1.整数转化为字符串:采用加'0',再逆序的办法,整数加'0'就会隐性转化成ch ...
- java udp 发送小数数字(较难)
代码全部来自:http://825635381.iteye.com/blog/2046882,在这里非常感谢了,我运行测试了下,非常正确,谢谢啊 服务端程序: package udpServer; i ...
- 一个web应用的诞生--数据表单
下面把角色分为两种,普通用户和管理员用户,至少对于普通用户来说,直接修改DB是不可取的,要有用户注册的功能,下面就开始进行用户注册的开发. 用户表 首先要想好用户注册的时候需要提供什么信息:用户名.密 ...
- ASP.NET应用程序的文件类型及文件夹列表
文件类型: 1. *.aspx文件:这类文件是ASP.NET Web页面,它包括用户接口和隐藏代码. 2. *.ascx文件:这类文件是用户控件.用户控件同Web页面非常相似,但用户不能直接访问用户控 ...
- Java安装
java特点:跨平台.简单.面向对像编译后解释再运行安装JDK 环境变量的配置:JAVA_HOME:JDK的根目录====C:\Program Files\Java\jdk1.7.0_25Path:J ...
- AngularJs ng-repeat指令中怎么实现含有自定义指令的动态html
今天用angular写table的时候,遇到了一个问题.在ng-repeat中,含有动态的html,而这些html中含有自定义指令. 因为希望实现一个能够复用的table,所以定义了一个指令mySta ...
- 【Zookeeper】源码分析之请求处理链(四)
一.前言 前面分析了SyncReqeustProcessor,接着分析请求处理链中最后的一个处理器FinalRequestProcessor. 二.FinalRequestProcessor源码分析 ...