sleep可以在任何地方调用。wait必须在synchronized中调用,否则抛出 IllegalMonitorStateException
Object a = new Object(); try { a.wait(); } catch (InterruptedException e) { e.printStackTrace(); }
输出
java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.example.threads.TestSleepAndWait.testWait(TestSleepAndWait.java:11)
正确使用wait:
@Test public void testWait() { Object lock = new Object(); synchronized (lock) { try { lock.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } @Test public synchronized void testWait2() { try { wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } }
sleep不会释放监视器锁。wait释放监视器锁(因此wait必须在synchronized中使用)
sleep的javadoc
/** * 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. */ public static native void sleep(long millis) throws InterruptedException;
wait的javadoc,原文太长做了截断
/* * The current thread must own this object's monitor. The thread * releases ownership of this monitor and waits until another thread * notifies threads waiting on this object's monitor to wake up * either through a call to the {@code notify} method or the * {@code notifyAll} method. The thread then waits until it can * re-obtain ownership of the monitor and resumes execution. */ public final void wait() throws InterruptedException { wait(0); }
@Test public void testSleepForMonitor(){ try { Thread.sleep(60000L); } catch (InterruptedException e) { e.printStackTrace(); } }
jps找到pid,再jstack打印thread dump。
C:/Users/ycwu>jps 3312 7744 RemoteMavenServer 13352 Jps 1884 Launcher 8476 JUnitStarter C:/Users/ycwu>jstack 8476
输出
"main" #1 prio=5 os_prio=0 tid=0x00000000029f3000 nid=0x2fdc waiting on condition [0x00000000028ae000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.example.threads.TestSleepAndWait.testSleepForMonitor(TestSleepAndWait.java:42)
@Test public synchronized void testWaitForMonitor(){ try { wait(60000L); } catch (InterruptedException e) { e.printStackTrace(); } }
jps找到pid,再jstack打印thread dump。
C:/Users/ycwu>jps 13408 JUnitStarter 3312 7744 RemoteMavenServer 13220 Launcher 13224 Jps C:/Users/ycwu>jstack 13408
输出
"main" #1 prio=5 os_prio=0 tid=0x0000000002ae3000 nid=0x91c in Object.wait() [0x000000000294e000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076c56cc18> (a com.example.threads.TestSleepAndWait) at com.example.threads.TestSleepAndWait.testWaitForMonitor(TestSleepAndWait.java:50) - locked <0x000000076c56cc18> (a com.example.threads.TestSleepAndWait)
从下往上看,先获取了锁( locked <0x000000076c56cc18>
),然后释放并且等待( waiting on <0x000000076c56cc18>
)。