這個在面試題目中常常出現,比較全的答案以下: a.sleep是Thread的靜態方法,能夠睡眠當前調用者進程,而wait是Object裏面的方法。 b.sleep不釋放鎖,而wait釋放鎖,使得其餘線程可使用同步方法或者同步控制塊(**可是注意sleep和wait都釋放出cpu的使用權**)。 c.wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep能夠在任何地方使用(使用範圍) synchronized(x){ x.notify() //或者wait() } d.sleep方法要處理異常,而wait不用處理異常。
其實最本質的區別的sleep不釋放鎖,而wait釋放鎖。示例:java
public class TestSynchronized { public void test1() { synchronized(this) { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); //sleep並不釋放對象鎖 } catch (InterruptedException ie) { } } } } public synchronized void test2() { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); //sleep並不釋放對象鎖 } catch (InterruptedException ie) { } } } public static void main(String[] args) { final TestSynchronized myt2 = new TestSynchronized(); Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" ); Thread test2 = new Thread( new Runnable() { public void run() { myt2.test2(); } }, "test2" ); test1.start();; test2.start(); } }
Java代碼 收藏代碼面試
test2 : 4 test2 : 3 test2 : 2 test2 : 1 test2 : 0 test1 : 4 test1 : 3 test1 : 2 test1 : 1 test1 : 0
若是將test1和test2裏面的sleep(500)換成wait(500),結果就以下:函數
test1 : 4 test2 : 4 test2 : 3 test1 : 3 test1 : 2 test2 : 2 test2 : 1 test1 : 1 test2 : 0 test1 : 0
2.擴充閱讀this
Java 線程中的sleep和wait有一個共同做用,中止當前線程任務運行,但他們存在必定的不一樣,首先咱們先看sleep中的構造函數
sleep(long millis) 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.
sleep(long millis, int nanos) Causes the currently executing thread to sleep (cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers.
sleep方法屬於Thread類中方法,表示讓一個線程進入睡眠狀態,等待必定的時間以後,自動醒來進入到可運行狀態,不會立刻進入運行狀態,由於線程調度機制恢復線程的運行也須要時間,一個線程對象調用了sleep方法以後,並不會釋放他所持有的全部對象鎖,因此也就不會影響其餘進程對象的運行。但在sleep的過程當中過程當中有可能被其餘對象調用它的interrupt(),產生InterruptedException異常,若是你的程序不捕獲這個異常,線程就會異常終止,進入TERMINATED狀態,若是你的程序捕獲了這個異常,那麼程序就會繼續執行catch語句塊(可能還有finally語句塊)以及之後的代碼。
注意sleep()方法是一個靜態方法,也就是說他只對當前對象有效,經過t.sleep()讓t對象進入sleep,這樣的作法是錯誤的,它只會是使當前線程被sleep 而不是t線程
wait方法
void wait(long timeout)
Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
void wait(long timeout, int nanos)
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
wait屬於Object的成員方法,一旦一個對象調用了wait方法,必需要採用notify()和notifyAll()方法喚醒該進程;若是線程擁有某個或某些對象的同步鎖,那麼在調用了wait()後,這個線程就會釋放它持有的全部同步資源,而不限於這個被調用了wait()方法的對象。wait()方法也一樣會在wait的過程當中有可能被其餘對象調用interrupt()方法而產生InterruptedException,效果以及處理方式同sleep()方法。線程
sleep()方法和wait()方法都成產生讓當前運行的線程中止運行的效果,這是它們的共同點。下面咱們來詳細說說它們的不一樣之處。code
sleep()方法是本地方法,屬於Thread類,它有兩種定義:對象
public static native void sleep(long millis) throws InterruptedException; public static void sleep(long millis, int nanos) throws InterruptedException { //other code }
其中的參數millis表明毫秒數(千分之一秒),nanos表明納秒數(十億分之一秒)。這兩個方法均可以讓調用它的線程沉睡(中止運行)指定的時間,到了這個時間,線程就會自動醒來,變爲可運行狀態(RUNNABLE),但這並不表示它立刻就會被運行,由於線程調度機制恢復線程的運行也須要時間。調用sleep()方法並不會讓線程釋放它所持有的同步鎖;並且在這期間它也不會阻礙其它線程的運行。上面的連個方法都聲明拋出一個InterruptedException類型的異常,這是由於線程在sleep()期間,有可能被持有它的引用的其它線程調用它的interrupt()方法而中斷。中斷一個線程會致使一個InterruptedException異常的產生,若是你的程序不捕獲這個異常,線程就會異常終止,進入TERMINATED狀態,若是你的程序捕獲了這個異常,那麼程序就會繼續執行catch語句塊(可能還有finally語句塊)以及之後的代碼。進程
爲了更好地理解interrupt()效果,咱們來看一下下面這個例子:事件
public class InterruptTest { public static void main(String[] args) { Thread t = new Thread() { public void run() { try { System.out.println("我被執行了-在sleep()方法前"); // 中止運行10分鐘 Thread.sleep(1000 * 60 * 60 * 10); System.out.println("我被執行了-在sleep()方法後"); } catch (InterruptedException e) { System.out.println("我被執行了-在catch語句塊中"); } System.out.println("我被執行了-在try{}語句塊後"); } }; // 啓動線程 t.start(); // 在sleep()結束前中斷它 t.interrupt(); } }
運行結果: 我被執行了-在sleep()方法前
我被執行了-在catch語句塊中
我被執行了-在try{}語句塊後ci
wait()方法也是本地方法,屬於Object類,有三個定義:
public final void wait() throws InterruptedException { //do something } public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { //do something }
wari()和wait(long timeout,int nanos)方法都是基於wait(long timeout)方法實現的。一樣地,timeout表明毫秒數,nanos表明納秒數。當調用了某個對象的wait()方法時,當前運行的線程就會轉入等待狀態(WAITING),等待別的線程再次調用這個對象的notify()或者notifyAll()方法(這兩個方法也是本地方法)喚醒它,或者到了指定的最大等待時間,線程自動醒來。若是線程擁有某個或某些對象的同步鎖,那麼在調用了wait()後,這個線程就會釋放它持有的全部同步資源,而不限於這個被調用了wait()方法的對象。wait()方法一樣會被Thread類的interrupt()方法中斷,併產生一個InterruptedException異常,效果同sleep()方法被中斷同樣。
第一種解釋:
功能差很少,都用來進行線程控制,他們最大本質的區別是:sleep()不釋放同步鎖,wait()釋放同步鎖.
喚醒方法不一樣:sleep(milliseconds)能夠用時間指定來使他自動醒過來,若是時間不到你只能調用interreput()來強行打斷;wait()能夠用notify()直接喚起.
第二種解釋:
sleep是Thread類的靜態方法。sleep的做用是讓線程休眠制定的時間,在時間到達時恢復,也就是說sleep將在接到時間到達事件時恢復線程執行,例如:
try{ System.out.println("I'm going to bed"); Thread.sleep(1000); System.out.println("I wake up"); }catch(IntrruptedException e) { }
wait是Object的方法,也就是說能夠對任意一個對象調用wait方法,調用wait方法將會將調用者的線程掛起,直到其餘線程調用同一個對象的notify方法纔會從新激活調用者,例如:
//Thread 1
try{ obj.wait(); //suspend thread until obj.notify() is called } catch(InterrputedException e) { }
第三種解釋:
這二者的施加者是有本質區別的. sleep()是讓某個線程暫停運行一段時間,其控制範圍是由當前線程決定,也就是說,在線程裏面決定.比如如說,我要作的事情是 "點火->燒水->煮麪",而當我點完火以後我不當即燒水,我要休息一段時間再燒.對於運行的主動權是由個人流程來控制.
而wait(),首先,這是由某個肯定的對象來調用的,將這個對象理解成一個傳話的人,當這我的在某個線程裏面說"暫停!",也是 thisOBJ.wait(),這裏的暫停是阻塞,仍是"點火->燒水->煮飯",thisOBJ就比如一個監督個人人站在我旁邊,原本該線程應該執行1後執行2,再執行3,而在2處被那個對象喊暫停,那麼我就會一直等在這裏而不執行3,但這個流程並無結束,我一直想去煮飯,但還沒被容許, 直到那個對象在某個地方說"通知暫停的線程啓動!",也就是thisOBJ.notify()的時候,那麼我就能夠煮飯了,這個被暫停的線程就會從暫停處繼續執行.
其實二者均可以讓線程暫停一段時間,可是本質的區別是一個線程的運行狀態控制,一個是線程之間的通信的問題
在java.lang.Thread類中,提供了sleep(),而java.lang.Object類中提供了wait(),notify()和notifyAll()方法來操做線程,sleep()能夠將一個線程睡眠,參數能夠指定一個時間。而wait()能夠將一個線程掛起,直到超時或者該線程被喚醒。