Java基礎wait和sleep的區別
1、sleep是Thread中的方法,是靜態方法,wait是Object中的方法,是實例方法。
2、sleep主要作用使線程暫停執行一段時間,時間一到自動恢復,不涉及線程通訊,不會去釋放鎖,但是wait會釋放這個鎖,並把這個wait的線程加入到這個鎖的等待隊列中去
3、sleep方法不依賴於同步器synchronized,但是wait需要依賴synchronized關鍵字。
4、sleep不需要被喚醒(休眠之後退出阻塞),但是wait需要(不指定時間需要被別人中斷)。
5、sleep一般用於當前線程休眠,或者輪循暫停操作,wait多用於多線程之間的通信。
sleep和wait使用時都需要捕獲InterruptedException異常,在調用後都會暫停當前線程,並讓出CPU的執行時間,但不同的是sleep不會釋放當前持有的對象的鎖資源, 到時間後會繼續執行,而wait會放棄所有鎖並需要notify/notifyAll後重新獲取到對象鎖資源後才能繼續執行。
Thread.sleep(1000) 意思是在未來的1000毫秒內本線程不參與CPU競爭,1000毫秒過去之後,這時候也許另外一個線程正在使用CPU,那麼這時候操作系統是不會重新分配CPU的,直到那個線程掛起或結束,即使這個時候恰巧輪到操作系統進行CPU分配,那麼當前線程也不一定就是總優先級最高的那個,CPU還是可能被其他線程搶占去。另外值得一提的是Thread.Sleep(0)的作用,就是觸發操作系統立刻重新進行一次CPU競爭,競爭的結果也許是當前線程仍然獲得CPU控制權,也許會換成別的線程獲得CPU控制權。
wait(1000)表示將鎖釋放1000毫秒,到時間後如果鎖沒有被其他線程佔用,則再次得到鎖,然後wait方法結束,執行後面的代碼,如果鎖被其他線程佔用,則等待其他線程釋放鎖。注意,設置了超時時間的wait方法一旦過了超時時間,並不需要其他線程執行notify也能自動解除阻塞,但是如果沒設置超時時間的wait方法必須等待其他線程執行notify。
sleep不會釋放鎖的例子如下:
public class SleepLockTest {
private final static Object lock = new Object();
public static void main(String[] args) {
Stream.of("thread1", "thread2").forEach(x -> new Thread(x) {
@Override
public void run() {
SleepLockTest.testSleep();
}
}.start());
}
private static void testSleep() {
synchronized (lock) {
try {
System.out.println(Thread.currentThread().getName() + " is running");
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + " finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
運行結果如下:
thread1 is running:1650637494109
thread1 finish
thread2 is running:1650637499111
thread2 finish
wait會釋放鎖的例子如下:
public class WaitLockTest {
private final static Object LOCK = new Object();
public static void main(String[] args) {
Stream.of("thread1", "thread2").forEach(x -> new Thread(x) {
@Override
public void run() {
WaitLockTest.testWait();
}
}.start());
}
private static void testWait() {
synchronized (LOCK) {
try {
System.out.println(Thread.currentThread().getName() + " is running:"+System.currentTimeMillis());
LOCK.wait();
System.out.println(Thread.currentThread().getName() + " finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
運行結果如下:
thread1 is running:1650637686502
thread2 is running:1650637686502
使用wait必須要定義一個synchronized,而sleep不需要
如下代碼wait沒有在synchronized代碼塊內
public class WaitNoSync {
private final static Object LOCK = new Object();
public static void main(String[] args) {
new Thread(() -> WaitNoSync.testWait()).start();
}
private static void testWait() {
try {
System.out.println(Thread.currentThread().getName() + " is running:" + System.currentTimeMillis());
LOCK.wait();
System.out.println(Thread.currentThread().getName() + " finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運行結果如下:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.company.thread.WaitNoSync.testWait(WaitNoSync.java:18)
at com.company.thread.WaitNoSync.lambda$main$0(WaitNoSync.java:11)
at java.lang.Thread.run(Thread.java:748)