之前面试, 背了下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