之前面试, 背了下sleep和wait的区别,蒙混过关了。 最近又准备面试, 发现sleep和wait的区别, 理解得还是不够。 于是想用段代码来验证下以加深下印象
一开始这么写的
public class SleepAndWait {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// runWait();
runSleep();
}
static void runSleep() throws InterruptedException {
Sleep s = new Sleep();
Thread t = new Thread(s, "Sleep线程");
System.out.println("程序开始");
t.start();
Thread.sleep(1000);
s.testSyncSleep();
}
}
class Sleep implements Runnable {
void testSleep() {
System.out.println("非sync方法可以执行");
}
synchronized void testSyncSleep() {
System.out.println("sync方法可以执行");
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始休眠5s");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "休眠完成");
}
}
一运行,问题马上出来了。 不是说,sleep不会释放对象锁吗?怎么执行sleep休眠时还可以运行testSyncSleep方法
搜了下资料,发现不少人也有同样的问题。
http://www.iteye.com/topic/1038812
http://www.iteye.com/problems/21645
归根结底, 真正的问题是, sleep到底是持有谁的锁?
到这里, 差不多能发现上面代码问题所在了, sleep前没加任何锁, 当然也就无法验证sleep不会释放对象锁的问题
重写了下代码,验证了下, 问题差不多明白了。
public class SleepAndWait {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
runWait();
// runSleep();
}
static void runWait() throws InterruptedException {
Wait s2 = new Wait();
Thread t2 = new Thread(s2, "Wait线程");
System.out.println("程序开始");
t2.start();
Thread.sleep(1000);
/*
* s2.testSyncWait 输出结果
*
* 程序开始
* Wait线程开始休眠5s
* sync方法可以执行
* Wait线程休眠完成
*/
// s2.testSyncWait();
/*
* s2.testWait 输出结果
*
* 程序开始
* Wait线程开始休眠5s
* 非sync方法可以执行
* Wait线程休眠完成
*/
// s2.testWait();
// 注意, 和非sync方法相比, sync方法明显没有被阻塞直到Wait线程休眠完成,
// 也就是说, wait时已经释放对象锁
}
static void runSleep() throws InterruptedException {
Sleep s = new Sleep();
Thread t = new Thread(s, "Sleep线程");
System.out.println("程序开始");
t.start();
Thread.sleep(1000);
/*
* s.testSleep() 输出结果
*
* 程序开始
* Sleep线程开始休眠5s
* 非sync方法可以执行
* Sleep线程休眠完成
*/
//s.testSleep();
/*
* s.testSyncSleep() 输出结果
* 程序开始
* Sleep线程开始休眠5s
* Sleep线程休眠完成
* sync方法可以执行
*/
//s.testSyncSleep();
// 注意, 和非sync方法相比, sync方法明显被阻塞直到Sleep线程休眠完成,
// 也就是说, sleep时没有释放对象锁
}
}
class Wait implements Runnable {
void testWait() {
System.out.println("非sync方法可以执行");
}
synchronized void testSyncWait() {
System.out.println("sync方法可以执行");
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始休眠5s");
try {
synchronized (this) {
wait(5000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "休眠完成");
}
}
class Sleep implements Runnable {
void testSleep() {
System.out.println("非sync方法可以执行");
}
synchronized void testSyncSleep() {
System.out.println("sync方法可以执行");
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始休眠5s");
try {
synchronized (this) {
Thread.sleep(5000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "休眠完成");
}
}
参考
java 之sleep(), yield(), wait(), notify(), join()的区别
http://dylanxu.iteye.com/blog/1322066