Java并发之(2):线程通信wait/notify(TIJ_21_5)
简介:
java中线程间同步的最基本的方式就是使用wait()¬ify()¬ifyAll(),它们是线程间的握手机制。除了上述方法,java5还在java.util.concurrent.Locks包中提供了condition接口,该接口声明了awake()&signal()方法,也是线程间同步的方式之一。 wait()/notify() 都是任意java object所具备的方法,它们通常与synchronized关键字配合使用,而condition一般与显式的重入锁配合使用。
语义:
Object.wait()把当前线程挂起,等待object.notify()或者object.notifyall()的执行。wait()可以替代busy waiting(通常以循环查询某条件是否已经具备的方式)。
object.notify()把等待object锁(monitor)的线程唤醒,通知其可以继续运行。如果有多个线程都在等待这个object的锁,则随机选择一个唤醒。同时当前线程继续执行。当另外一个线程调用该java对象的notify()方法时,将“唤醒”等待该java对象的那个线程。
notifyAll()将唤醒所有在等待的线程;notify()仅唤醒一个正在等待的线程,如果有多个线程在等待,会随机选择一个唤醒。
Wait:
为了正确地执行object.wait()方法,当前线程必须已经获得了该object的锁。也就是说,只有在同步方法或者同步块(synchronized)中,才能调用wait方法。执行object.wait()方法意味着当前线程释放该锁,当前线程挂起,直到有另外线程执行object.notify()方法。 wait()有三种方式,带纳秒参数的::
public final void wait(long timeout, int nanos) throws InterruptedException {
带毫秒参数的 :
public final native void wait(long timeout) throws InterruptedException;
和不带参数的:
public final void wait() throws InterruptedException {
其中wait()使用的比较多。
纳秒级的等待?
看wait的第一种实现,很有意思:
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}
nanos好像并没有发挥什么作用。 这是Java8在Windows平台下的JDK的源码。注意如果是实时操作系统的话,nanos就有可能发挥作用,但是在Windows下,nanos目前并没有发挥作用。这是因为虽然cpu的时钟周期是纳秒级的,但是Windows操作系统并不支持这么细粒度的时间间隔。
在调用wait时还有一点要特别注意:
永远在一个循环中调用wait()方法。因为如果多个线程都在等待同一个锁,然后其中一个得到了这个锁,然后会重置等待的条件,然后其他线程需要在它们醒来以后检查循环条件,以此来决定它们是需要再次等待,还是开始执行。
notify:
为了调用某个java对象的notify()方法,你必须在同一个java对象上同步(synchronized),或者说在一个同步的上下文中:
synchronized (someObject) {
someObject.wait(); // 释放锁,不对。应该在一个循环中调用wait方法
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
尽量少使用wait/notify:
从Java5开始,java sdk中的java.util.conconrrent包中主要提供了三种与线程同步(不是synchronization,不是lock之类的线程互 斥)相关的类: Executor相关框架、并发容器(BlockinQueue)、和一些同步工具(Synchronizers,倒计数锁存器等)。这些同步工具主要是通用的同步类,主要用于线程间的协作。同步工具主要包括Condition、CountdownLatch、CyclicBarrier、Semaphore、CyclicBarrier、phasers和exchangers等。
一般而言,在java5或者更新的java版本中,wait()¬ify()很少显式地使用。因为很多标准库中的类已经实现了wait()/notify()的功能。比如:
- 在Java5中,可以使用新的BlockingQueue实现,来实现生产者和消费者模型。
- Java5中的显式锁类,比标准的synchronized关键字提供了更多的功能,比如带超时的tryLock。在Java5之前这个功能需要使用 wait()/notify()才能实现;
- 可以使用Semaphore控制资源池。
操作系统线程问题中的概念
关键段CS critical section、事件Event、互斥量Mutex 信号量等概念 如何与java多线程中的概念映射???
互斥量:
跟锁的概念十分类似。
信号量:
操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,acquire()获取一个许可,如果没有就等待,而 release()释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。
Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能,但实现上要复杂些,代码也要复杂些。
参考文献:
http://blog.csdn.net/zyplus/article/details/6672775
http://javamex.com/tutorials/synchronization_wait_notify.shtml
http://www.javamex.com/tutorials/synchronization_producer_consumer.shtml
http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml
http://www.javamex.com/tutorials/synchronization_concurrency_semaphore.shtml
http://blog.csdn.net/zyplus/article/details/6672775
http://www.javamex.com/tutorials/synchronization_wait_notify.shtml
http://blog.csdn.net/morewindows/article/details/7481609
http://blog.csdn.net/morewindows/article/details/7442639
http://blog.csdn.net/morewindows/article/details/7445233
http://blog.csdn.net/morewindows/article/details/7442333
http://stackoverflow.com/questions/6553225/whats-the-purpose-of-sleeplong-millis-int-nanos
Java并发之(2):线程通信wait/notify(TIJ_21_5)的更多相关文章
- java并发编程基础——线程通信
线程通信 当线程在系统内运行时,程序通常无法准确的控制线程的轮换执行,但我们可以通过一些机制来保障线程的协调运行 一.传统的线程通信 传统的线程通信主要是通过Object类提供的wait(),noti ...
- Java并发编程原理与实战二十一:线程通信wait¬ify&join
wait和notify wait和notify可以实现线程之间的通信,当一个线程执行不满足条件时可以调用wait方法将线程置为等待状态,当另一个线程执行到等待线程可以执行的条件时,调用notify可以 ...
- java多线程 -- Condition 控制线程通信
Api文档如此定义: Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对 ...
- java 多线程 day13 condition 线程通信
/** * Created by chengtao on 17/12/5. * Condition 类似 wait和notify,解决线程间的同步问题 */ import java.util.conc ...
- Java并发之ThreadPoolExecutor 线程执行服务
package com.thread.test.thread; import java.util.concurrent.ExecutorService; import java.util.concur ...
- java并发之停止线程
停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作.停止一个线程可以用Thread.stop()方法,但最好不要用它.虽然它确实可以停止一个正在运行的线程,但是这个方法是不安 ...
- Java线程通信-生产者消费者问题
线程通信示例——生产者消费者问题 这类问题描述了一种情况,假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费.假设仓库中没有产品,则生产者可以将 产品放入仓库,有 ...
- 【Java并发编程】:使用wait/notify/notifyAll实现线程间通信
在java中,可以通过配合调用Object对象的wait()方法和notify()方法或notifyAll()方法来实现线程间的通信.在线程中调用wait()方法,将阻塞等待其他线程的通知(其他线程调 ...
- Java并发之线程间的同步协作与通信协作
1,Monitor监视器与syncrhoized实现原理 1.1:Monitor Monitor是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量. 它内置与每一个Object对 ...
随机推荐
- Android 环信 调用相机崩掉 mikdir()
protected void selectPicFromCamera() { if (!EaseCommonUtils.isSdcardExist()) { Toast.makeText(getAct ...
- Hyper-V 2016 配置管理系列(准备篇)
2.1 推荐软硬件配置 2.2 Hyper主机前提准备 前提条件: 具有二级地址转换(SLAT)的64位处理器.要安装Hyper-V虚拟化组件(如Windows管理程序),处理器必须具有SLAT 足够 ...
- hihocoder第三十六周 二分查找
题目链接:http://hihocoder.com/contest/hiho36/problem/1 , 一个比较简单的二分. 算法: 由于数据量比较大,O(nlogn)无法通过,所以不能先排序再查找 ...
- java之打印机服务通俗做法
javax.print包是API的主包,其中包含的类和接口能够让你:1)发现打印服务(Print Services)2)指定打印数据的格式 3)从一个打印服务创建打印工作(print jobs) 4) ...
- Linux下bash的快捷键
Ctrl + A :切换到命令行开始 Ctrl + E :切换到命令行末尾 Ctrl + L : 清屏,相当于clear Ctrl + U :清除剪切光标前的内容 Ctrl + K :剪切清除光标后 ...
- Feign + Hystrix 服务熔断和服务降级
本机IP为 192.168.1.102 1. 新建 Maven 项目 feign 2. pom.xml <project xmlns="http://maven.apa ...
- java 如何使的float保留2位或者多位小数
方法1: float f = 34.232323; BigDecimal b = new BigDecimal(f); float f1 = b.set ...
- java算法面试题:金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。
package com.swift; public class RenMingBi { private static final char[] data = new char[]{'零','壹','贰 ...
- git出现误修改如何撤销
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file. 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步, ...
- 数据库引擎InnoDB和myisam的区别和联系
1.ENGINE=InnoDB 数据库存储引擎,DEFAULT 默认,CHARSET=utf8 数据库字符编码 2.数据库的存储引擎, mysql中engine=innodb和engine=myisa ...