对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。
package Demo0422TestSynchronized;
/**
* java中的sleep()和wait()的区别
*
* @author Hongten
* @date 2013-12-10
*/
public class TestD {
public static void main(String[] args) {
new Thread(new Thread1(),"线程1").start();
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + "****睡5秒****");
} catch (Exception e) {
e.printStackTrace();
}
new Thread(new Thread2(),"线程2").start();
}
private static class Thread1 implements Runnable {
@Override
public void run() {
synchronized (TestD.class) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting...");
try {
// 调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池
TestD.class.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread1 is going on ....");
System.out.println("thread1 is over!!!");
TestD.class.notifyAll();
}
}
}
private static class Thread2 implements Runnable {
@Override
public void run() {
synchronized (TestD.class) {
System.out.println("enter thread2....");
System.out.println("thread2 is sleep....");
// 只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
System.out.println(Thread.currentThread().getName()+"将会唤醒另一个线程");
TestD.class.notify();
// ==================
// 区别
// 如果我们把代码:TestD.class.notify();给注释掉,即TestD.class调用了wait()方法,但是没有调用notify()
// 方法,则线程永远处于挂起状态。
try {
// sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,
// 但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
// 在调用sleep()方法的过程中,线程不会释放对象锁。
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread2 is going on....");
System.out.println("thread2 is over!!!");
System.out.println(Thread.currentThread().getName() + "即将结束, 结束之前再睡10秒 后进入等待状态");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
TestD.class.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
程序运行结果:
enter thread1...
thread1 is waiting...
main****睡5秒****
enter thread2....
thread2 is sleep....
线程2将会唤醒另一个线程
thread2 is going on....
thread2 is over!!!
线程2即将结束, 结束之前再睡10秒
thread1 is going on ....
thread1 is over!!!
等待唤醒机制与synchronized
所谓等待唤醒机制本篇主要指的是notify/notifyAll和wait方法,在使用这3个方法时,必须处于synchronized代码块或者synchronized方法中,否则就会抛出IllegalMonitorStateException异常,这是因为调用这几个方法前必须拿到当前对象的监视器monitor对象,也就是说notify/notifyAll和wait方法依赖于monitor对象,在前面的分析中,我们知道monitor 存在于对象头的Mark Word 中(存储monitor引用指针),而synchronized关键字可以获取 monitor ,这也就是为什么notify/notifyAll和wait方法必须在synchronized代码块或者synchronized方法调用的原因。
synchronized (obj) {
obj.wait();
obj.notify();
obj.notifyAll();
}
需要特别理解的一点是,与sleep方法不同的是wait方法调用完成后,线程将被暂停,但wait方法将会释放当前持有的监视器锁(monitor),直到有线程调用notify/notifyAll方法后方能继续执行,而sleep方法只让线程休眠并不释放锁。同时notify/notifyAll方法调用后,并不会马上释放监视器锁,而是在相应的synchronized(){}/synchronized方法执行结束后才自动释放锁。