今天看到一篇問題,提問線程喚醒順序。
具體代碼如下:
import java.util.LinkedList;
import java.util.List;
public class ThreadRunSort {
/**
* 對象鎖
*/
private final Object object = new Object();
private List<Integer> sleep = new LinkedList<>();
private List<Integer> notify = new LinkedList<>();
/**
* 該線程作爲一個喚醒線程
*/
public void startThread(int i) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
try {
System.out.println(Thread.currentThread().getName()+"進入休眠");
sleep.add(i);
object.wait();
System.out.println(Thread.currentThread().getName()+"線程已經喚醒");
notify.add(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.setName("Thread"+i);
t.start();
}
public static void main(String[] args) {
ThreadRunSort a = new ThreadRunSort();
for(int i =1;i<22;i++){
a.startThread(i);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
for(int i =1;i<22;i++){
synchronized (a.object) {
a.object.notify();
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("休眠順序"+a.sleep);
System.out.println("喚醒順序"+a.notify);
}
}
發現,輸入的順序是不定的,比如:
休眠順序[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[1, 5, 4, 3, 2, 7, 6, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 21]
但是,當修改了其中notify代碼:
for(int i =1;i<22;i++){
try {
Thread.sleep(10); // 在這裏sleep確保notify會順序執行
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a.object) {
a.object.notify();
}
}
順序就變成
休眠順序[1, 3, 4, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[1, 3, 4, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
可以理解在wait時候,放入的是一個FIFO的隊列?每次notify其實就是出隊的形式。(上面順序有問題是因爲線程按順序出隊後,搶佔鎖的順序和CPU有關)
但是,把代碼改成notifyAll後:
休眠順序[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
變成了stack出棧的形式。。
具體的問題還要再研究下。。。。