请详细的讲解wait和sleep wait 区别和notify

下次自动登录
现在的位置:
& 综合 & 正文
JAVA wait(), notify(),sleep详解
在CSDN开了博客后,一直也没在上面发布过,直到前一段时间与一位前辈的对话,才发现技术博客的重要,立志要把CSDN的博客建好。但一直没有找到好的开篇的主题,今天再看JAVA线程互斥、同步的时候又有了新的体会,就以他作为开篇吧。
在JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static
XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。
Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
单单在概念上理解清楚了还不够,需要在实际的例子中进行测试才能更好的理解。对Object.wait(),Object.notify()的应用最经典的例子,应该是三线程打印ABC的问题了吧,这是一道比较经典的面试题,题目要求如下:
建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。如下:
public class MyThreadPrinter2 implements Runnable {
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name =
this.prev =
this.self =
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start();
先来解释一下其整体思路,从大的方向上来讲,该问题为三线程间的同步唤醒操作,主要的目的就是ThreadA-&ThreadB-&ThreadC-&ThreadA循环执行三个线程。为了控制线程执行的顺序,那么就必须要确定唤醒、等待的顺序,所以每一个线程必须同时持有两个对象锁,才能继续执行。一个对象锁是prev,就是前一个线程所持有的对象锁。还有一个就是自身对象锁。主要的思想就是,为了控制执行的顺序,必须要先持有prev锁,也就前一个线程要释放自身对象锁,再去申请自身对象锁,两者兼备时打印,之后首先调用self.notify()释放自身对象锁,唤醒下一个等待线程,再调用prev.wait()释放prev对象锁,终止当前线程,等待循环结束后再次被唤醒。运行上述代码,可以发现三个线程循环打印ABC,共10次。运行的主要过程就是A线程最先运行,持有C,A对象锁,后释放A,C锁,唤醒B。线程B等待A锁,再申请B锁,后打印B,再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C,B锁,唤醒A。看起来似乎没什么问题,但如果你仔细想一下,就会发现有问题,就是初始条件,三个线程按照A,B,C的顺序来启动,按照前面的思考,A唤醒B,B唤醒C,C再唤醒A。但是这种假设依赖于JVM中线程调度、执行的顺序。具体来说就是,在main主线程启动ThreadA后,需要在ThreadA执行完,在prev.wait()等待时,再切回线程启动ThreadB,ThreadB执行完,在prev.wait()等待时,再切回主线程,启动ThreadC,只有JVM按照这个线程运行顺序执行,才能保证输出的结果是正确的。而这依赖于JVM的具体实现。考虑一种情况,如下:如果主线程在启动A后,执行A,过程中又切回主线程,启动了ThreadB,ThreadC,之后,由于A线程尚未释放self.notify,也就是B需要在synchronized(prev)处等待,而这时C却调用synchronized(prev)获取了对b的对象锁。这样,在A调用完后,同时ThreadB获取了prev也就是a的对象锁,ThreadC的执行条件就已经满足了,会打印C,之后释放c,及b的对象锁,这时ThreadB具备了运行条件,会打印B,也就是循环变成了ACBACB了。这种情况,可以通过在run中主动释放CPU,来进行模拟。代码如下:
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
Thread.sleep(1);
catch (InterruptedException e){
e.printStackTrace();
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
运行后的打印结果就变成了ACBACB了。为了避免这种与JVM调度有关的不确定性。需要让A,B,C三个线程以确定的顺序启动,最终代码如下:
public class MyThreadPrinter2 implements Runnable {
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name =
this.prev =
this.self =
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
Thread.sleep(1);
catch (InterruptedException e){
e.printStackTrace();
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);
new Thread(pa).start();
Thread.sleep(10);
new Thread(pb).start();
Thread.sleep(10);
new Thread(pc).start();
Thread.sleep(10);
这样才可以完美的解决该问题。通过这个例子也是想说明一下,很多理论、概念如Obj.wait(),Obj.notify()等,理解起来,比较简单,但是在实际的应用当中,这里却是往往出现问题的地方。需要更加深入的理解。并在解决问题的过程中不断加深对概念的掌握。
——欢迎转载,请注明出处 ——
&&&&推荐文章:
【上篇】【下篇】请详细的讲解wait和sleep wait 区别和notify - 叫阿莫西中心 - 中国网络使得骄傲马戏中心!
请详细的讲解wait和sleep wait 区别和notify
本文转自:
在CSDN开了博客后,一直也没在上面发布过文章,直到前一段时间与一位前辈的对话,才发现技术博客的重要,立志要把CSDN的博客建好。但一直没有找到好的开篇的主题,今天再看JAVA线程互斥、同步的时候又有了新的体会,就以他作为开篇吧。
&&& 在JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static
XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。
&&& Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
单单在概念上理解清楚了还不够,需要在实际的例子中进行测试才能更好的理解。对Object.wait(),Object.notify()的应用最经典的例子,应该是三线程打印ABC的问题了吧,这是一道比较经典的面试题,题目要求如下:
建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。代码如下:
public class MyThreadPrinter2 implements Runnable {
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name =
this.prev =
this.self =
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2(&A&, c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2(&B&, a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2(&C&, b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start();
先来解释一下其整体思路,从大的方向上来讲,该问题为三线程间的同步唤醒操作,主要的目的就是ThreadA-&ThreadB-&ThreadC-&ThreadA循环执行三个线程。为了控制线程执行的顺序,那么就必须要确定唤醒、等待的顺序,所以每一个线程必须同时持有两个对象锁,才能继续执行。一个对象锁是prev,就是前一个线程所持有的对象锁。还有一个就是自身对象锁。主要的思想就是,为了控制执行的顺序,必须要先持有prev锁,也就前一个线程要释放自身对象锁,再去申请自身对象锁,两者兼备时打印,之后首先调用self.notify()释放自身对象锁,唤醒下一个等待线程,再调用prev.wait()释放prev对象锁,终止当前线程,等待循环结束后再次被唤醒。运行上述代码,可以发现三个线程循环打印ABC,共10次。程序运行的主要过程就是A线程最先运行,持有C,A对象锁,后释放A,C锁,唤醒B。线程B等待A锁,再申请B锁,后打印B,再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C,B锁,唤醒A。看起来似乎没什么问题,但如果你仔细想一下,就会发现有问题,就是初始条件,三个线程按照A,B,C的顺序来启动,按照前面的思考,A唤醒B,B唤醒C,C再唤醒A。但是这种假设依赖于JVM中线程调度、执行的顺序。具体来说就是,在main主线程启动ThreadA后,需要在ThreadA执行完,在prev.wait()等待时,再切回线程启动ThreadB,ThreadB执行完,在prev.wait()等待时,再切回主线程,启动ThreadC,只有JVM按照这个线程运行顺序执行,才能保证输出的结果是正确的。而这依赖于JVM的具体实现。考虑一种情况,如下:如果主线程在启动A后,执行A,过程中又切回主线程,启动了ThreadB,ThreadC,之后,由于A线程尚未释放self.notify,也就是B需要在synchronized(prev)处等待,而这时C却调用synchronized(prev)获取了对b的对象锁。这样,在A调用完后,同时ThreadB获取了prev也就是a的对象锁,ThreadC的执行条件就已经满足了,会打印C,之后释放c,及b的对象锁,这时ThreadB具备了运行条件,会打印B,也就是循环变成了ACBACB了。这种情况,可以通过在run中主动释放CPU,来进行模拟。代码如下:
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
Thread.sleep(1);
catch (InterruptedException e){
e.printStackTrace();
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
& & 运行后的打印结果就变成了ACBACB了。为了避免这种与JVM调度有关的不确定性。需要让A,B,C三个线程以确定的顺序启动,最终代码如下:
public class MyThreadPrinter2 implements Runnable {
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name =
this.prev =
this.self =
public void run() {
int count = 10;
while (count & 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
Thread.sleep(1);
catch (InterruptedException e){
e.printStackTrace();
self.notify();
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2(&A&, c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2(&B&, a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2(&C&, b, c);
new Thread(pa).start();
Thread.sleep(10);
new Thread(pb).start();
Thread.sleep(10);
new Thread(pc).start();
Thread.sleep(10);
& & &这样才可以完美的解决该问题。通过这个例子也是想说明一下,很多理论、概念如Obj.wait(),Obj.notify()等,理解起来,比较简单,但是在实际的应用当中,这里却是往往出现问题的地方。需要更加深入的理解。并在解决问题的过程中不断加深对概念的掌握。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:75259次
积分:1181
积分:1181
排名:第16175名
原创:36篇
转载:25篇
评论:28条
(2)(1)(2)(2)(4)(1)(1)(1)(6)(2)(5)(1)(1)(5)(13)(10)(1)(3)(1)Thread的wait sleep join yield suspend notify区别_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
3页免费7页免费14页免费3页免费3页1下载券2页免费2页免费1页免费2页免费3页免费
喜欢此文档的还喜欢3页免费7页免费40页7下载券4页1下载券148页7下载券
Thread的wait sleep join yield suspend notify区别|
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢学习多Thread编程,对这几个方法的理解非常重要,然而他们却难以掌握。今天就专门看了看API,下面进行简短的说明:synchronized在学习这几个方法前,先要明白synchronized的用法。synchronized就是为对象指定监听,哪个线程在执行synchronized修饰的代码块,就是监听哪个线程。synchronized的用法:public class A(){
private static int
private Object lock=new Object();
private int// 为this上锁
public synchronized int add(){
return i++;
public int add2(){// 为this上锁
synchronized(this){
return i++;
} // 为A.class上锁
public static synchronized int add3(){
return b++;
}// 为lock对象上锁
public int add4(){
synchronized(lock){
return i++;
}} Synchronized的用法&&使用了synchronized就是为某个对象锁定当前线程,也称为线程拥有了对象的监听(monitor)。&了解了这个之后,再来看看下面的要说的几个方法:&notify()&Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.只唤醒等待object的监听的多个线程中的任意一个。通过调用wait方法可以让线程去等待object的监听。The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchr for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.被唤醒的线程不会立即就可以处理操作(被唤醒后,是脱离了阻塞状态,转为可执行状态),而是到当前的线程释放了object的锁。This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways(这三种方式就对应了上面说的synchronized的用法):By executing a synchronized instance method of that object.By executing the body of a synchronized statement that synchronizes on the object.For objects of type Class, by executing a synchronized static method of that class.Only one thread at a time can own an object's monitor.这段话就是说:notify()要在synchronized修饰的语句块中。&为啥notify()需要在synchronized块中呢?&notify是唤醒等待的线程的,说明当前线程不是处于等待状态,而是处于监听状态,因此需要在synchronized块中。&&&&&&&&&&&wait()&Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.让当前线程去等待,直到其他线程来唤醒它,或者等的时间片完毕。The current thread must own this object's monitor.This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.Object调用了wait,会让当前线程释放掉与object的关联,并被放到等待集合中(也就是让当前线程释放掉CPU时间片,失去与object的锁定,处于阻塞状态)。Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.Some other thread invokes the notifyAll method for this object.Some other thread interrupts thread T.The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.有四种方式可以让线程脱离等待:&其他线程调用执行时调用了notify(),并且现象处于轮流的被唤醒、被关闭状态(其实就是阻塞状态)。&其他线程调用了notifyAll()&别的线程打断了线程T。&指定的等待时间完毕。总结一下就是:线程脱离阻塞状态的三种方式:被唤醒、等待时间完毕:这两种会进入可执行状态。被打断(会抛异常的):这种会让线程die。&如果不指定等待时间(或者指定等待时间为0),那就等着别的线程唤醒你吧。&The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synch once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.线程T被唤醒后,就从等待集合中被移除(脱离阻塞状态)。如果唤醒线程,线程T一旦获取到了Object的控制权(被object监听),线程T就会还原等待前的状态,然后接着原来的位置开始执行。&If the current thread is interrupted by any thread before or while it is waiting, then an InterruptedException is thrown. This exception is not thrown until the lock status of this object has been restored as described above.一旦线程(处于等待状态或者等待前)一旦被任意一个线程打断(包括它自己,打断的方式是调用interrupt()方法),就会在线程获取到object控制权,并还原等待前的状态,要接着执行时,抛出InterruptedException。This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.Wait要在synchronized中使用。&也就是说wait的使用是这样的:synchronized(this){//xxxxxthis.wait();}是这样的:synchronized void method (){wait();}&是这样的:static synchronized void method(){clazz.wait();// clazz代表一个Class对象}&是这样的:synchronized(lock){lock.wait();}&也就是说,对谁使用了synchronized,就用谁的wait方法。&&&&sleep()&Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.让当前线程休息一会,但对象仍旧拥有object的监听,没有与Object切断联系。没有切断联系,别的线程就不能拿到锁定执行。&&sleep与wait的都能让当前线程先不执行。但wait会 让当前线程失去监听,sleep不会。&&join()&join不好理解,Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.根据上面的说明,很容易理解为:等待当前线程死了,至少得等待指定的毫秒数。如果指定时间为0,那就是一种等下去。&&&package com.fjn.other.threadTpublic class ThreadTest{&& private final long _1S=1000L;&&&& public void testJoin(){&&&&& Thread aThread=new Thread(new Runnable() {&&&&&&&&&&&&&& public void run() {&&&&&&&&&& for (int i = 0; i & 10; i++) {&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&& Thread.sleep(_1S);&&&&&&&&&&&&& && System.out.println(Thread.currentThread().getName()+&:/t&+i);&&&&&&&&&&&&& } catch (InterruptedException e) {&&&&&&&&&&&&&&&& e.printStackTrace();&&&&&&&&&&&&& }&&&&&&&&&& }&&&&&&& }&&&&& },&Thread-A&);&&&&& aThread.start();&&&&&&&&&& new Thread(new Runnable() {&&&&&&& public void run() {&&&&&&&&&& for (int i = 0; i & 10; i++) {&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&& Thread.sleep(_1S*2);&&&&&&&&&&&&& && System.out.println(Thread.currentThread().getName()+&:/t&+i);&&&&&&&&&&&&& } catch (InterruptedException e) {&&&&&&&&&&&&&&&& e.printStackTrace();&&&&&&&&&&&&& }&&&&&&&&&& }&&&&&&&&&&&&&&&&& }&&&&& },&Thread-B&).start();&& }&&&& public static void main(String[] args) {&&&&& new ThreadTest().testJoin();&& }}&&上面的代码执行是这样的(只取了一部分结果):Thread-A:& 0Thread-A:& 1Thread-B:& 0Thread-A:& 2Thread-A:& 3Thread-B:& 1Thread-A:& 4Thread-A:& 5Thread-B:& 2Thread-A:& 6Thread-A:& 7Thread-B:& 3Thread-A:& 8&然后加上join:&package com.fjn.other.threadTpublic class ThreadTest{&& private final long _1S=1000L;&&&& public void testJoin(){&&&&& Thread aThread=new Thread(new Runnable() {&&&&&&&&&&&&&& public void run() {&&&&&&&&&& for (int i = 0; i & 10; i++) {&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&& Thread.sleep(_1S);&&&&&&&&&&&&& && System.out.println(Thread.currentThread().getName()+&:/t&+i);&&&&&&&&&&&&& } catch (InterruptedException e) {&&&&&&&&&&&&&&&& e.printStackTrace();&&&&&&&&&&&&& }&&&&&&&&&& }&&&&&&& }&&&&& },&Thread-A&);&&&&& aThread.start();&&&&& try {&&&&&&& aThread.join();&&&&& } catch (InterruptedException e1) {&&&&&&& e1.printStackTrace();&&&&& }&&&&& new Thread(new Runnable() {&&&&&&& public void run() {&&&&&&&&&& for (int i = 0; i & 10; i++) {&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&& Thread.sleep(_1S*2);&&&&&&&&&&&&& && System.out.println(Thread.currentThread().getName()+&:/t&+i);&&&&&&&&&&&&& } catch (InterruptedException e) {&&&&&&&&&&&&&&&& e.printStackTrace();&&&&&&&&&&&&& }&&&&&&&&&& }&&&&&&&&&&&&&&&&& }&&&&& },&Thread-B&).start();&& }&&&& public static void main(String[] args) {&&&&& new ThreadTest().testJoin();&& }}&&我以为结果应该是:aThread等死了。线程B正常执行。但结果是这样的:Thread-A:& 0Thread-A:& 1Thread-A:& 2Thread-A:& 3Thread-A:& 4Thread-A:& 5Thread-A:& 6Thread-A:& 7Thread-A:& 8Thread-A:& 9Thread-B:& 0Thread-B:& 1Thread-B:& 2Thread-B:& 3Thread-B:& 4Thread-B:& 5Thread-B:& 6Thread-B:& 7Thread-B:& 8Thread-B:& 9从结果来看是,线程A正常执行完毕后,才执行线程B。&这是为什么呢???不理解,网上说的也不明确,看源码:public final synchronized void join(long millis)&&& throws InterruptedException {&& long base = System.currentTimeMillis();&& long now = 0;&&& if (millis & 0) {&&&&&&&&&&& throw new IllegalArgumentException(&timeout value is negative&);&& }&&& if (millis == 0) {&& &&& while (isAlive()) {&&&&& wait(0);&& &&& }&& } else {&& &&& while (isAlive()) {&&&&& long delay = millis -&&&&& if (delay &= 0) {&&&&& &&&&&&&& }&&&&& wait(delay);&&&&& now = System.currentTimeMillis() -&& &&& }&& }&&& }指定时间为0:就是执行:while(isAlive()){wait(0)}意思是说:指定时间为0,就直接执行wait(0)。上面说wait()是让当前线程等待呀,如果wait(0),就等着别的线程notify呀。上面的代码中,是不可能有别的线程notify的呀。那也就是说Thread-A是永远不能被唤醒的呀,不能被唤醒,就不能再获得对象锁呀,当然Thread-A就不能继续往下走呀。分析的结果是这样的,实际的结果却是那样的,为什么呢??????&在重新看源码:上面说了:对谁使用了synchronized,就用谁的wait()。也就是说,源码中是对aThread对象使用了synchronized,也就是说让当前线程等待,等待继续获取到aThread对象的监听。也就是说:不是让aThread等待,而是让当前线程等aThread。等aThread死了,就是等aThread执行完毕而死或者被打断而死。&那上面的代码的意思就是,让main线程等待,等到aThread执行完毕,然后开始执行main。所以上面的代码的执行过程应该是:main执行过程中,1、创建aThread对象2、启动aThread,aThread开始执行。3、main执行join(),让自己等待,等aThread执行完毕4、aThread执行完毕,main继续执行5、创建B线程并开始执行&在看join()的说明:Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.等待指定时间,等待this.join()中的this代表的线程去死。如果时间为0,就一直等到this代表的线程死亡。如果时间不为0,就等待指定时间就行了,如果this线程没有死也不等了。&&&interrupt()&Interrupts this thread.Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.If none of the previous conditions hold then this thread's interrupt status will be set.Interrupting a thread that is not alive need not have any effect.&
无相关信息温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
阅读(229)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_083067',
blogTitle:'进程sleep,wait,join,yield,notify(),notifyAll(),run(),start(),Synchronized的区别',
blogAbstract:'1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有Synchronized同步块,其他线程仍然不同访问共享数据。注意该方法要捕获异常\r\n比如有两个线程同时执行(没有Synchronized),一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完成后,低优先级的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。\r\n总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:0,
permalink:'blog/static/',
commentCount:1,
mainCommentCount:1,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length&0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index&4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length&0}
{list newslist as x}
{if x_index&7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!=&-1&) },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}
说的太好了,我顶!
Copyright & 2014
Corporation, All Rights Reserved
Processed in 2.7617 second(s), 5 db_queries,
1 rpc_queries

我要回帖

更多关于 sleep wait 区别 的文章

 

随机推荐