文档章节

java并发(一)wait,notify的使用

风荷举
 风荷举
发布于 2013/10/17 22:32
字数 961
阅读 1978
收藏 2

Java是第一个内置对多线程支持的主流编程语言。在Java5之前,对多线程的支持主要是通过对块结构的同步实现的(synchronized配合wait,notify,notifyAll),Java5引入了java.util.concurrent包,提供了对多线程编程的更高层的支持。

在Java中,除了int等基本类型之外,一切皆为对象。synchronized关键字以及Object类中的wait,notify和notifyAll方法为我们编写多线程程序提供了原始的支持。

例如:


public class A {
	public synchronized void fun() {
		...
	}
}

在调用方法fun之前,调用该方法的执行线程必须要先获得类A的实例(a)的对象锁。上面的方法fun在功能上等同于:

public void fun() {
	synchronized(this) {
		...
	}
}
在执行fun之前,要获取a的对象锁,在方法fun返回之前,要释放a的对象锁。

通常可以使用synchronized和notify,notifyAll以及wait方法来实现线程之间的数据传递及控制。对于对象obj来说:

  • obj.wait():该方法的调用,使得调用该方法的执行线程(T1)放弃obj的对象锁并阻塞,直到别的线程调用了obj的notifyAll方法、或者别的线程调用了obj的notify方法且JVM选择唤醒(T1),被唤醒的线程(T1)依旧阻塞在wait方法中,与其它的线程一起争夺obj的对象锁,直到它再次获得了obj的对象锁之后,才能从wait方法中返回。(除了notify方法,wait还有带有时间参数的版本,在等待了超过所设时间之后,T1线程一样会被唤醒,进入到争夺obj对象锁的行列;另外中断可以直接跳出wait方法)
  • obj.notify():该方法的调用,会从所有正在等待obj对象锁的线程中,唤醒其中的一个(选择算法依赖于不同实现),被唤醒的线程此时加入到了obj对象锁的争夺之中,然而该notify方法的执行线程此时并未释放obj的对象锁,而是离开synchronized代码块时释放。因此在notify方法之后,synchronized代码块结束之前,所有其他被唤醒的,等待obj对象锁的线程依旧被阻塞。
  • obj.notifyAll():与notify的区别是,该方法会唤醒所有正在等待obj对象锁的线程。(不过同一时刻,也只有一个线程可以拥有obj的对象锁)

要注意的是,wai,notify以及notifyAll方法的调用必须在相应的synchronized代码块之中。例如:


synchronized(obj) {
	while(xxx) {
		obj.wait();
	}
	...
}

下面写个小例子,来说明wait方法返回之前要重新获得对象锁,以及notify方法执行之后并不立即释放对象锁。

public class MThread implements Runnable {
	public synchronized void assign() {
		this.notifyAll();
		System.err.println("out of notifyAll");
		while(true){}
	}
	
	public synchronized void await() throws InterruptedException {
		this.wait(5000);
		System.err.println("out of wait");
	}

	@Override
	public void run() {
			try {
				await();
			} catch (InterruptedException e) {
			}
	}

}


public class Main {
	public static void main(String[] args) {
		MThread mThread = new MThread();
		Thread thread = new Thread(mThread);
		thread.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		mThread.assign();
	}
}
主线程中,先创建子线程,并启动,主线程sleep一秒钟是为了让子线程中的this.wait(5000)得到执行,而wait(5000)又保证在五秒钟结束之前,主线程中的mThread.assign()方法得到调用,进而调用子线程的notifyAll方法,来唤醒wait方法。从执行结果中可以看到“out of notifyAll”的输出,却始终看不到“out of wait”,这说明notifyAll方法执行完成,而wait方法并未返回。一个合理的解释就是wait还在等待mThread的对象锁,而notifyAll执行完成后也并未立即释放mThread的对象锁,sun的官方文档的说明也是如此。

十点半了,哎,第一次发博客,不知如何,有点小忐忑



© 著作权归作者所有

共有 人打赏支持
风荷举
粉丝 11
博文 24
码字总数 24803
作品 0
朝阳
程序员
私信 提问
加载中

评论(1)

jiucheng
jiucheng
0支持一下
Java多线程学习(四)等待/通知(wait/notify)机制

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
2018/04/16
0
0
好文收集之JAVA并发:线程间的协作(wait/notify/sleep/yield/join)

Java 并发编程:线程间的协作(wait/notify/sleep/yield/join) 博文开始复习了下线程状态,给出了线程状态间的转换图示。 以实例,源码,解释描述方式,阐述了wait, notify ,sleep等的功能 点...

ol_O_O_lo
02/27
0
0
面试系列-并发编程72道面试题及答案

话不多说直接上题,篇幅限制,文末有答案 1.Java中守护线程和本地线程区别 2.线程与进程的区别 3.什么是多线程中的上下文切换 4.死锁与活锁的区别,死锁与饥饿的区别 5.Java中用到的线程调度...

Java邵先生
01/29
0
0
JAVA多线程-基础Synchronized

后篇: JAVA多线程-基础Lock Condition 并发集合 JAVA多线程-交互计算 Future Callable Promise 读懂代码,首先要懂得thread的几个状态,以及它们之间的转换. Java thread的状态有new, runnable...

xpbug
2012/11/07
0
10
Java线程面试题 Top 50

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者...

loda0128
2015/05/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux iptables之mangle表使用案例

mangle表的用途 mangle表的主要功能是根据规则修改数据包的一些标志位,以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 mangel表使用示例 示例1-策略路由1 内网的客户机通...

月下狼
42分钟前
2
0
OSChina 周日乱弹 —— 兼职我想去学学布偶戏

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @clouddyy : 《火炎 - 女王蜂》 《火炎 - 女王蜂》 手机党少年们想听歌,请使劲儿戳(这里) @小鱼丁 :还在睡觉突然接到一个小哥哥电话“x...

小小编辑
55分钟前
54
4
租房软件隐私保护如同虚设

近日,苏州市民赵先生向江苏新闻广播新闻热线025-84658888反映,他在“安居客”手机应用软件上浏览二手房信息,并且使用该软件自动生成的虚拟号码向当地一家中介公司进行咨询。可电话刚挂不久...

linux-tao
今天
3
0
分布式项目(五)iot-pgsql

书接上回,在Mapping server中,我们已经把数据都整理好了,现在利用postgresql存储历史数据。 iot-pgsql 构建iot-pgsql模块,这里我们写数据库为了性能考虑不在使用mybatis,换成spring jd...

lelinked
今天
6
0
一文分析java基础面试题中易出错考点

前言 这篇文章主要针对的是笔试题中出现的通过查看代码执行结果选择正确答案题材。 正式进入题目内容: 1、(单选题)下面代码的输出结果是什么? public class Base { private Strin...

一看就喷亏的小猿
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部