深入线程的wait()/notify()

转载 2006年05月19日 14:42:00

最近看线程,今天复习时发觉自己并没有搞明白sleep,interrupt和wait,notify的区别,以前曾见人这么分析二者:

  sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)"醒来"的线程具有更高的优先级。 (b)正在运行的线程因为其它原因而阻塞。
  wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

      但我还是不怎么明白,就跑去论坛上找文章,看到了下面这篇,讲的不错,收录下来。

下面是我原来在CJSDN论坛上看到的一个贴子,涉及到同步,wait(),notify()等概念的理解,我试着根据原来的一些回复和Think in Java上的相关概念将wait()和notify()这两个方法剖析了一下,欢迎指教.

问题如下:

file://分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!
class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
System.out.println("b is start....");
synchronized(b)//括号里的b是什么意思,起什么作用?
{
try
{
System.out.println("Waiting for b to complete...");
b.wait();//这一句是什么意思,究竟让谁wait?
System.out.println("Completed.Now back to main thread");
}catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}
}

class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB is running..");
for (int i=0;i<100;i++ )
{
total +=i;
System.out.println("total is "+total);
}
notify();
}
}
}

要分析这个程序,首先要理解notify()和wait(),为什么在前几天纪录线程的时候没有纪录这两个方法呢,因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,每个对象都有notify和wait的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.

再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是wait()和notify了.

按照Think in Java中的解释:"wait()允许我们将线程置入"睡眠"状态,同时又"积极"地等待条件发生改变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."

我们来解释一下这句话.
"wait()允许我们将线程置入"睡眠"状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的.那和sleep,suspend有什么区别呢?

区别在于"(wait)同时又"积极"地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放.
而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况下(sleep啊,suspend啊),这是不可能的.
但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个对象锁收回来的呀.wait什么?就是wait别人用完了还给我啊!
好,那怎么把对象锁收回来呢?
第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回.
第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来.哎,假如我设了1小时之后收回,别人只用了半小时就完了,那怎么办呢?*!当然用完了就收回了,还管我设的是多长时间啊.

那么别人怎么通知我呢?相信大家都可以想到了,notify(),这就是最后一句话"而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒"的意思了.
因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().

这个时候我们来解释上面的程序,简直是易如反掌了.

synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行.

主线程去控制子线程wait与notify

  • 2015年05月04日 22:19
  • 965KB
  • 下载

java线程的join,wait,notify深入理解

对于thread的理解,一直停留在基本层面,想着加强一下理解。Ok,问题总是有的,当然收获也是美滋滋的。 先从一下demo开始lz的探索之旅,一步步揭开那神秘的面纱。 public class J...
  • wjbtian
  • wjbtian
  • 2014年02月20日 11:56
  • 1888

JAVA多线程-线程间通信(一)-等待/通知机制(wait/notify)

线程间通信     线程与线程之间不是独立的个体,它们彼此之间可以相互通信与协作。     线程间通信后,系统之间的交互性会更强大,在大大提交CPU利用率的同时,还会使程序要对各线程任务在处理的过...

object的notify、wait对线程使用的理解

在线程中,notify、wait的会唤醒一个

android 线程 wait notify

线程状态 1.程序通过Thread t = new Thread(),调用t.start()启动一个线程,使该线程进入可运行(Runnable)的状态。 2.由JVM的决定去调度(...

Java线程wait/notify讲解

wait:当前访问对象的线程被阻塞,并且放弃之前拥有的对象锁,直到被notify/notifyAll方法唤醒,在原来中断的地方继续执行 扩展:线程从原来中断的地方继续执行的原因:操作系统是同意管理...

Java线程中的wait(),notify()与sleep()

在Java中可以通过wait()与notify()或notifyAll()实现线程协作。简要总结有如下几点: 1.wait()让线程进入等待状态,并释放锁(而sleep等待的同时并不释放锁) 2....
  • ucxiii
  • ucxiii
  • 2016年09月28日 00:33
  • 335

再谈关于 java 线程,synchronized,wait,notify

我可以明确告诉你,不可能有一个单线程程序里有 wait 这类代码的出现,因为要是真这样,线程一但wait ,再也没人叫醒他了,绝不可能有这样的程序出现。...
  • cnmm22
  • cnmm22
  • 2015年03月30日 21:40
  • 419

Java多线程编程3--线程间通信--等待(wait)/通知(notify)机制

1、什么是等待/通知机制     等待/通知机制在生活中比比皆是,比如在就餐时就会出现,如图所示。     厨师和服务员之间的交互要在“菜品传递台”上,在这期间会有几个问题:     1)厨师做完一...

jvm的线程之间的通信-notify-wait-notifyAll

超类 Object 类 使用 native code 实现的 线程之间的 通信是怎样的?
  • whdblog
  • whdblog
  • 2017年05月15日 21:50
  • 90
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入线程的wait()/notify()
举报原因:
原因补充:

(最多只允许输入30个字)