Java 多線程基礎(七)線程休眠 sleep
一、線程休眠 sleep
sleep() 方法定義在Thread.java中,是 static 修飾的靜态方法。
sleep() 的作用是讓目前線程休眠,即目前線程會從“運作狀态”進入到“休眠(阻塞)狀态”。sleep()會指定休眠時間,線程休眠的時間會大于/等于該休眠時間;線上程重新被喚醒時,它會由“阻塞狀态”變成“就緒狀态”,進而等待cpu的排程執行。
二、sleep示例
public classSleepTest {private static Object obj = newObject();public static voidmain(String[] args) {
Thread t1= new MyThread("t1");t1.start();
}static class MyThread extendsThread{publicMyThread(String name) {super(name);
}public voidrun() {synchronized(obj) {try{for(int i = 0;i < 5;i++) {
System.out.println(Thread.currentThread().getName()+ "--" +i);if (i % 4 == 0)
Thread.sleep(1000);//i能被4整除時,休眠1秒
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
//運作結果
t1--0t1--1t1--2t1--3t1--4
說明:
在主線程main中啟動線程t1。t1啟動之後,當t1中的計算i能被4整除時,t1會通過Thread.sleep(100)休眠100毫秒。
三、sleep(long millis) 與 wait(long timeout)
我們知道,wait()的作用是讓目前線程由“運作狀态”進入“等待(阻塞)狀态”的同時,也會釋放同步鎖。而sleep()的作用是也是讓目前線程由“運作狀态”進入到“休眠(阻塞)狀态”。
但是,wait() 會釋放對象的同步鎖,而 sleep() 則不會釋放鎖。
通過下面的代碼,示範 sleep() 不會釋放鎖的:
public classSleepTest {private static Object obj = newObject();public static voidmain(String[] args) {
Thread t1= new MyThread("t1");
Thread t2= new MyThread("t2");
t1.start();
t2.start();
}static class MyThread extendsThread{publicMyThread(String name) {super(name);
}public voidrun() {synchronized(obj) {try{for(int i = 0;i < 5;i++) {
System.out.println(Thread.currentThread().getName()+ "--" +i);Thread.sleep(1000);//休眠1秒
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
//執行結果
t1--0t1--1t1--2t1--3t1--4t2--0t2--1t2--2t2--3t2--4
說明:
主線程main中啟動了兩個線程t1和t2。t1和t2在run()會引用同一個對象的同步鎖,即synchronized(obj)。在t1運作過程中,雖然它會調用Thread.sleep(1000) 進入休眠狀态;但是,t2是不會擷取CPU執行權的。因為,t1并沒有釋放“obj所持有的同步鎖”!
注意,若我們注釋掉 synchronized (obj) 後再次執行該程式,t1和t2是可以互相切換執行的,原因是:在沒有同步鎖的情況下,當一個線程進入“休眠(阻塞)狀态“時,會放棄CPU的執行權,另一個線程就會擷取CPU執行權。
通過下面的代碼,示範 wait() 會釋放鎖的:
public classSleepTest {private static Object obj = newObject();public static voidmain(String[] args) {
Thread t1= new MyThread("t1");
Thread t2= new MyThread("t2");
t1.start();
t2.start();
}static class MyThread extendsThread{publicMyThread(String name) {super(name);
}public voidrun() {synchronized(obj) {try{for(int i = 0;i < 5;i++) {
System.out.println(Thread.currentThread().getName()+ "--" +i);
obj.wait(1000);//等待1秒
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
//執行結果
t1--0t2--0t1--1t2--1t2--2t1--2t2--3t1--3t2--4t1--4
說明:
主線程main中啟動了兩個線程t1和t2。t1和t2在run()會引用同一個對象的同步鎖,即synchronized(obj)。在t1運作過程中,調用 obj.wait(1000) 進入等待狀态,釋放同步鎖;此時,t2會擷取CPU執行權的。