Java Object中wait()和notify()小议
来源:互联网 发布:网络种地 编辑:程序博客网 时间:2024/06/05 13:03
最近在学习Java中线程同步和线程通信问题,发现在Java基础类Object中有两个线程相关方法wait()和notify(),于是就做了点小的实验,下面就是实验的内容。
在介绍实验之前我们要弄清楚synchronized关键字的真正语义。
synchronized关键字是用来声明在执行某个代码块时,执行该代码块的线程必须获得某个特定对象的对象监视器(java 官方称其为moniter,民间传说称其为锁,下面我一概简称监视器),而一个对象的监视器只有一个。这句话什么意思呢,我们来看个例子代码。
StringBuffer sb = new StringBuffer();
synchronized(sb){//代码段1}
这段代码就是说当某个线程要执行代码段1时,该线程必须先获取对象sb的监视器,同时该线程将会持有该监视器一直到代码段1执行完毕才会将其释放。我们知道,一个对象的监视器只有一个,如果该对象的监视器被线程线程A持有了,那么任何其他线程在执行形如上面的代码时,也就是说在执行需要获取监视器的代码块时,都会被阻塞,因为他们要等待线程A释放掉监视器,也就是说等待线程A把同步代码块执行结束,他们才有可能获取处理器。
在方法前加synchronized其实就相当于
public void functionName(){
synchronized(this){
//方法执行代码
}
}
下面我们来看段代码
一般我们写线程等待会写成这样:
synchronized(obj){
//调用obj的方法
Thread.sleep(10000);
//调用obj的方法
}
在上面的代码中我调用了sleep方法是线程休眠的10秒,通过上面对synchronized的解释,我们知道如果有另一个线程要获取obj的监视器以执行同步代码块是不行的,虽然休眠的线程没有在执行,但是它却持有着obj的监视器,因此其他任何需要obj监视器才能执行的代码都必须等待。
wait()的作用就是使线程阻塞并且会暂时释放掉对象的监视器,notify()方法则是通知那些暂时释放监视器的线程回收监视器(注意这里只是通知,并不是立即,具体什么时候回收后面会解释)。
代码段2
synchronized(obj){
//调用obj的方法1
obj.wait()
//调用obj的方法2
}
代码段3
synchronized(obj){
//调用obj中的某些方法
obj.notify()
}
上面两段代码的执行都需要线程获取obj的监视器,而在代码段2中的wait将会阻塞当前线程,有就是说当调用了obj的方法1之后线程不会继续掉用obj的方法2而是将线程转为阻塞状态。按照我上面对synchronized的解释,当线程没有将代码段2中的代码全部执行完,其他线程是没有资格去执行代码段3的,但是wait()却可以让代码段3得到执行,因为wait()将会暂时释放掉obj的监视器,那么就是说代码段3就能够获取obj的监视器了,换言之代码段3就可以执行了。
在代码段3中我们调用了obj中的一些方法,最后我们调用了obj.notify()方法,它是干嘛的呢?现在我们假设执行代码段2的线程叫线程B,执行代码段3的线程叫线程C。线程B是阻塞的,但它暂时释放了obj的监视器,当前线程C是持有obj的监视器的,那儿在线程C中调用了obj.notify就是在通知线程B回收暂时释放的obj的监视器,同时会将线程B转为就绪状态。那么这个时候线程B是否就回收了obj的监视器呢?答案是:没有。那什么时候回收呢?当线程B从就绪状态转为执行状态时,线程B就是立即回收obj的监视器,然后执行obj的方法2。
下面是我实际测试时用的代码,通过分析运行结果和我上面的结论相信很好理解。
package individual.hcx.test;
public class Test {
public static void main(String[] args) throws Exception{
StringBuffer sb = new StringBuffer();
MyThread thread = new MyThread(sb);
MyThread2 thread2 = new MyThread2(sb);
thread2.start();
Thread.sleep(100);
thread.start();
}
}
class MyThread extends Thread{
StringBuffer sb;
public MyThread(StringBuffer sb){
this.sb = sb;
}
@Override
public void run(){
do{
synchronized(sb)
{
System.out.println("生成随机数!");
sb.delete(0, sb.length());
sb.append((int)(Math.random()*100));
sb.notify();
}
}while(true);
}
}
class MyThread2 extends Thread{
StringBuffer sb;
public MyThread2(StringBuffer sb){
this.sb = sb;
}
@Override
public void run(){
synchronized (sb) {
while(true){
System.out.println("sb = " + sb);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
try {
sb.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
在最后,wait()方法有两个重载的方法,他们的作用是让线程阻塞特定时间后还没有获得notify的通知,自动自己回收对象监视器。notify和notifyAll方法的却别是,notify是从全部等待的线程中随机选取一个通知它,notifyAll是通知全部在等待的线程。
0 0
- Java Object中wait()和notify()小议
- Object中wait和notify
- java Object 类中 notify() ,notifyAll() ,wait()
- java Object中的wait和notify方法
- java中 wait 和notify
- java中wait和notify
- java 中的 object.wait()和object.notify()的分析
- 记录java.lang.IllegalMonitorStateException错误,分析Object中wait()和notify()方法含义
- java线程中wait和notify 辨别
- Java多线程中wait()和notify()
- 线程中 Object对象的wait和notify方法使用,
- java wait和notify
- Java object类方法notify和wait分析
- Java学习整理之Object的wait和notify方法
- java Object类的wait和notify学习
- Object的Wait() 和notify()方法使用
- java中wait/notify机制
- java中wait/notify机制
- java多线程生命周期
- android资源目录---assets与res/raw的不同assets
- YII框架分析笔记6:视图
- Yii学习笔记:关闭layout
- hdu 4288 分组线段树
- Java Object中wait()和notify()小议
- Yii学习笔记:进一步简化,提示信息跳转页面
- TCP编程(三)
- PHP最佳实践----phpass
- 2014年6月23日-6月29日(共11小时,剩4424小时)
- 请问如何修改Yii默认跳转的登录页面地址
- 管理者的三多三少
- esd emc 1
- 用oracle发送邮件