在多線程中使線程阻塞有那麼幾種情況:
- sleep()的調用
- wait()的調用
- 遇到阻塞io
- suspend使線程暫停執行(這個方法已棄用)
- 在未持有鎖時,進入同一個對象鎖的同步代碼塊時,等待鎖的時候。
那麼我們這篇文章就看一看sleep()和wait()分别都能幹什麼。
sleep()
Thread.sleep(long millis),可以使目前線程休眠指定的毫秒數。但是需要注意的是,調用該方法并不會釋放鎖,我們通過代碼來看:
class T extends Thread{
@Override
synchronized public void run() {
for(int i = ; i < ; i++){
System.out.println(Thread.currentThread().getName() + ": " + i);
if(i == ){
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String[] args){
T t = new T();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.setName("線程1");
t2.setName("線程2");
t1.start();
t2.start();
}
}
結果:
線程:
線程:
線程:
線程:
線程:
線程: // 這裡雖然線程暫停了執行,但是線程2并沒有搶到執行權
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
運作得知,該代碼中雖然在i==5的時候,使線程sleep了,但是,線程并沒有釋放鎖,是以該代碼還是同步執行的。
wait()
這個方法可以帶上參數或者不帶參數,不帶參數的時候需要手動顯示的去notify(),才可以将該線程喚醒,在這之前線程是一直阻塞的,而帶參數的話是在一段時間内,如果都沒有将該線程喚醒,則會自動喚醒該線程,這裡我們使用帶參數的wait方法:
class T extends Thread{
@Override
synchronized public void run() {
for(int i = ; i < ; i++){
System.out.println(Thread.currentThread().getName() + ": " + i);
if(i == ){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String[] args){
T t = new T();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.setName("線程1");
t2.setName("線程2");
t1.start();
t2.start();
}
}
結果:
線程:
線程:
線程:
線程:
線程:
線程: // 這裡可以看出,線程立馬釋放了鎖,讓線程2搶到了執行權
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程:
線程: