Sau khi thực hiện wait (), một luồng sẽ đợi bao lâu nếu nó không nhận được thông báo từ các luồng khác?
Trong ví dụ dưới đây, vì luồng chính không nhận được thông báo từ luồng con, nên nó sẽ đợi mãi mãi. Nhưng luồng chính đang được thực thi và kết quả của ví dụ dưới đây là:
c
l
total: 19900
Tại sao luồng chính được thực thi?
public class ThreadX extends Thread {
static int total = 0;
public void run() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
total = total + i;
}
System.out.println("c");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadX t = new ThreadX();
t.start();
synchronized (t) {
t.wait();
System.out.println("l");
}
System.out.println("total: " + total);
}
}
Trả lời
Câu trả lời cho phần câu hỏi
Kiểm tra Thread#join(long):
[...] Khi một luồng kết thúc
this.notifyAll
phương thức được gọi. [...]
Lưu ý rằng Thread#join()
gọi hàm đó với 0
, có nghĩa là mãi mãi.
[...] Thời gian chờ bằng 0 có nghĩa là chờ đợi mãi mãi.
Vì vậy, trong trường hợp của bạn ở đây t
chỉ gọi notifyAll
khi nó kết thúc, điều này sẽ thông báo cho luồng chính đang chờ t
.
Hành vi không trực quan này là lý do tại sao họ viết như sau trong tài liệu:
Đó là khuyến cáo rằng các ứng dụng không sử dụng
wait
,notify
hoặcnotifyAll
vàoThread
trường.
Câu trả lời cho câu hỏi-tiêu đề
Kiểm tra Object#wait(hoặc JLS (17.2.1. Chờ) ):
Một chuỗi có thể đánh thức mà không bị thông báo, bị gián đoạn hoặc hết thời gian, được gọi là đánh thức giả. Trong khi điều này hiếm khi xảy ra trong thực tế, các ứng dụng phải đề phòng nó bằng cách kiểm tra điều kiện mà lẽ ra phải đánh thức luồng và tiếp tục chờ nếu điều kiện không được thỏa mãn.
Vì vậy, các luồng trong Java có thể đánh thức bất cứ lúc nào. Việc đánh thức giả không có khả năng xảy ra nhưng nó có thể xảy ra.