Sự khác biệt giữa chờ () và ngủ ()


1204

Sự khác biệt giữa a wait()sleep()trong Chủ đề là gì?

Có phải tôi hiểu rằng một wait()-ing Thread vẫn ở chế độ chạy và sử dụng các chu kỳ CPU nhưng một sleep()-ing không tiêu thụ bất kỳ chu kỳ CPU nào đúng không?

Tại sao chúng ta có cả hai wait()sleep(): làm thế nào để thực hiện chúng khác nhau ở cấp độ thấp hơn?


50
câu hỏi rất hay ngữ nghĩa của cả hai rất dễ nhầm lẫn.
Andreas Petersson

1
Những câu hỏi rất hay nhưng chúng là 2 trong một. Tại sao chúng ta có cả hai không giống như cách chúng có thể (và không phải!) Được thực hiện ở cấp thấp hơn. Tôi cũng đã trả lời như vậy.
estani

Giả sử một luồng A nằm trong một khối được đồng bộ hóa và trong khi nó ở trong cpu từ luồng này được lấy và đưa cho một luồng khác B. bây giờ, trạng thái của luồng A sẽ đi, các luồng khác đang chờ trên khối được đồng bộ hóa này sẽ xuất hiện ngay bây giờ ?
Peter

1
Đây là một bài viết hay mô tả về nó: qat.com/USE-waitnotify-instead-thread-s ngủ
Triton Man

3
Nó hoàn toàn ngược lại - ngủ "sử dụng" tất cả các chu kỳ CPU có sẵn của nó, nhưng vì luồng sẽ ở trạng thái "WAITING", nên chúng có thể được tạo ra nếu cần - thực tế là hầu hết các hệ điều hành đều tự động mang lại chu kỳ NẾU có thể, do đó luồng của bạn sẽ không tạo ra bất kỳ tải CPU thực tế nào ... mặc dù vậy, nó sẽ làm như vậy trên các hệ điều hành cũ hơn. Mặt khác, Object.wait () KHÔNG BAO GIỜ sử dụng bất kỳ chu trình nào (trong khi không được chú ý) bởi vì điều đó được nhận ra thông qua các ngắt phần mềm trong nhiều trường hợp - khóa riêng, tạm thời và trong suốt, được JVM triển khai. Thread.s ngủ là thực hành xấu.
đặc biệt

Câu trả lời:


838

A waitcó thể được "đánh thức" bởi một luồng khác đang gọi notifytrên màn hình đang chờ trong khi sleepkhông thể. Ngoài ra, một wait(và notify) phải xảy ra trong một khối synchronizedtrên đối tượng màn hình trong khi sleepkhông:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

Tại thời điểm này, luồng hiện đang chờ và giải phóng màn hình . Một chủ đề khác có thể làm

synchronized (mon) { mon.notify(); }

(trên cùng một monđối tượng) và luồng đầu tiên (giả sử đó là luồng duy nhất đang chờ trên màn hình) sẽ thức dậy.

Bạn cũng có thể gọi notifyAllnếu có nhiều hơn một luồng đang chờ trên màn hình - điều này sẽ đánh thức tất cả chúng . Tuy nhiên, chỉ một trong số các luồng sẽ có thể lấy màn hình (hãy nhớ rằng nó waitnằm trong một synchronizedkhối) và tiếp tục - những luồng khác sẽ bị chặn cho đến khi chúng có thể có được khóa của màn hình.

Điểm khác là bạn gọi waitvào Objectchính nó (tức là bạn chờ đợi trên màn hình của một đối tượng) trong khi bạn gọi sleeptrên Thread.

Tuy nhiên, một điểm khác là bạn có thể nhận được các đánh thức giả từ wait(tức là chuỗi đang chờ tiếp tục mà không có lý do rõ ràng). Bạn phải luôn luôn waitquay trong một số điều kiện như sau:

synchronized {
    while (!condition) { mon.wait(); }
}

131
Không, nó không thể. Nó chỉ có thể bị gián đoạn.
Peter tibraný

9
Khi bạn bị gián đoạn, bạn phải biết chủ đề nào bạn muốn ngắt. Khi bạn gọi điện thông báo, bạn chỉ cần đối tượng và bạn không quan tâm nếu có bất kỳ luồng nào khác 'chờ' trên đối tượng này. chờ đợi / thông báo được sử dụng để liên lạc, trong khi giấc ngủ được sử dụng cho, ehm, ngủ.
Peter tibraný

28
@Geek - tại sao trên thế giới bạn nói Wait () lãng phí chu kỳ CPU?
Robert Munteanu

25
Gián đoạn được dự định như một cơ chế để nhẹ nhàng khuyến khích một luồng ngừng chạy hoàn toàn và hủy các hoạt động còn lại. wait/ notifythường được sử dụng để chờ một số luồng khác hoàn thành một nhiệm vụ hoặc chờ cho đến khi một điều kiện nhất định được thỏa mãn.
Louis Wasserman

13
Tôi đọc qua tất cả các câu trả lời tuy nhiên tôi vẫn cảm thấy một chút thông tin bị thiếu. Nhiều người đã viết ra các định nghĩa từ Javadoc và cả ý nghĩa của hai từ tiếng Anh nhưng tôi không thấy Tại sao tôi nên sử dụng giấc ngủ thay vì chờ đợi? Điểm chuẩn và sự khác biệt tốc độ giữa hai là gì? Nếu tôi có thể làm mọi thứ mà tôi có thể làm với giấc ngủ thì tại sao tôi phải chọn ngủ?
Balazs Zsoldos

334

Một điểm khác biệt quan trọng chưa được đề cập là trong khi ngủ, Thread không giải phóng các khóa mà nó giữ, trong khi chờ đợi sẽ giải phóng khóa trên đối tượng wait()được gọi.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

105
Chờ đợi chỉ phát hành khóa cho đối tượng bạn gọi Wait () trên. Nó không phát hành bất kỳ ổ khóa khác .
Jon Skeet

16
Bạn thực sự không cần phải gọi giấc ngủ từ trong ổ khóa - khóa và chờ / thông báo song hành nhưng khóa và giấc ngủ không liên quan.
oxbow_lakes

7
@oxbow_lakes - Tôi muốn nói rằng bạn không nên ngủ với ổ khóa, có vài trường hợp sử dụng cho việc đó. Chỉ muốn chỉ ra sự khác biệt.
Robert Munteanu

5
@RobertMunteanu, Câu trả lời của bạn tuyên bố sai lầm sleepgiữ các khóa java , nhưng nó không. Để có một so sánh công bằng, chúng tôi sẽ so sánh synchronized(OUTER_LOCK){ Thread.sleep(1000); }với synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }và chúng tôi có thể thấy rằng cả hai hướng dẫn không phát hành OUTER_LOCK. Nếu có bất kỳ sự khác biệt nào, chúng ta có thể nói rằng sleepkhông sử dụng khóa java một cách rõ ràng , nhưng câu hỏi đặt ra là trích dẫn "cách thực hiện của chúng khác nhau ở mức thấp hơn?" bỏ qua
Pacerier

2
@Pacerier wait()được liên kết với tình trạng của hầu hết các khóa bên trong mà nó được gọi từ, trong ví dụ mã của bạn, wait()chỉ có thể phát hành LOCKvà không OUTER_LOCK. Đó là cách màn hình Java được thiết kế. Một so sánh công bằng sẽ là synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. Trong trường hợp sleep()này sẽ giữ cả hai khóa trong khi wait()sẽ phát hành LOCKnhưng vẫn giữOUTER_LOCK
danze

244

Tôi thấy bài viết này hữu ích. Nó đặt phần chênh lệch giữa Thread.sleep(), Thread.yield()Object.wait()về con người. Để trích:

Cuối cùng, tất cả đều đi xuống lịch trình của HĐH, nơi đưa ra các khoảng thời gian cho các tiến trình và luồng.

sleep(n)nói rằng tôi đã hoàn thành công việc của mình và xin đừng cho tôi một lần nữa trong ít nhất n mili giây. HĐH thậm chí không cố gắng lên lịch trình ngủ cho đến khi thời gian yêu cầu trôi qua.

yield()Nói rằng tôi đã hoàn thành công việc của mình, nhưng tôi vẫn còn việc phải làm. HĐH có thể tự do cung cấp cho luồng một thời gian khác hoặc đưa ra một số luồng khác hoặc xử lý CPU luồng xử lý vừa từ bỏ.

wait()Nói rằng tôi đã hoàn thành với thời gian của mình. Đừng cho tôi thời gian khác cho đến khi ai đó gọi thông báo (). Cũng như vậy sleep(), HĐH thậm chí sẽ không cố gắng lên lịch cho nhiệm vụ của bạn trừ khi có ai đó gọi notify()(hoặc một trong một vài tình huống đánh thức khác xảy ra).

Chủ đề cũng mất phần còn lại của thời gian của họ khi họ thực hiện chặn IO và trong một vài trường hợp khác. Nếu một luồng hoạt động trong toàn bộ thời gian, HĐH buộc phải kiểm soát một cách thô bạo như thể yield()đã được gọi, để các tiến trình khác có thể chạy.

Bạn hiếm khi cần yield(), nhưng nếu bạn có một ứng dụng nặng tính toán với các ranh giới nhiệm vụ hợp lý, việc chèn một ứng dụng yield() có thể cải thiện khả năng phản hồi của hệ thống (tốn thời gian - chuyển đổi ngữ cảnh, thậm chí chỉ cho HĐH và trở lại, không miễn phí). Đo lường và kiểm tra đối với các mục tiêu bạn quan tâm, như mọi khi.


Năng suất về cơ bản phụ thuộc vào nền tảng ... javamex.com/tutorials/threads/yield.shtml
Pacerier

lời giải thích sleep(n)ngầm là nói rằng luồng hiện đang chạy tự nguyện từ bỏ màn hình của khóa, điều đó không đúng . Trích dẫn từ javadoc của Thread : "Chủ đề không mất quyền sở hữu của bất kỳ màn hình nào."
Clint Eastwood

2
@Jonathan không có đề cập đến các màn hình trong câu trả lời và đó là vì sleepkhông có bất kỳ hành vi đặc biệt nào liên quan đến màn hình so với bất kỳ lệnh gọi phương thức Java nào khác, nghĩa là nó không tương tác hoặc sửa đổi chúng theo bất kỳ cách nào. Nếu bạn muốn nói điều gì đó về màn hình, bạn nên xác định điều đó wait, ngoài những điều đã nói ở trên, tạm thời từ bỏ khóa trên đối tượng mà nó được gọi.
pqnet

Làm thế nào để thông báo làm việc ở cấp độ lập lịch hệ điều hành? Có thông báo gọi một số loại trình xử lý sự kiện với một id luồng cụ thể, cho phép bộ lập lịch đưa luồng liên quan trở lại hàng đợi đang chạy không? Ngoài ra tôi có một câu hỏi khác, khái niệm spinlock phù hợp ở đâu? Nó sẽ chỉ có liên quan đến giấc ngủ hay chờ đợi nó sử dụng spinlock ở mức rất thấp?
CMCDragonkai 7/07/2015

@Erich, Dùng wait(n)để so sánh với sleep(n). Không có ý nghĩa trong việc so sánh bằng cách sử dụng không có đối số.
Pacerier

68

Có rất nhiều câu trả lời ở đây nhưng tôi không thể tìm thấy sự khác biệt về ngữ nghĩa được đề cập trên bất kỳ.

Đó không phải là về chủ đề chính nó; cả hai phương pháp đều được yêu cầu vì chúng hỗ trợ các trường hợp sử dụng rất khác nhau.

sleep()gửi Thread đi ngủ như trước đây, nó chỉ đóng gói bối cảnh và dừng thực thi trong một thời gian được xác định trước. Vì vậy, để đánh thức nó trước thời hạn, bạn cần biết tham chiếu Thread. Đây không phải là một tình huống phổ biến trong một môi trường đa luồng. Nó chủ yếu được sử dụng để đồng bộ hóa thời gian (ví dụ: thức dậy trong chính xác 3,5 giây) và / hoặc sự công bằng được mã hóa cứng (chỉ ngủ một lúc và để các luồng khác hoạt động).

wait(), ngược lại, là một cơ chế đồng bộ hóa luồng (hoặc tin nhắn) cho phép bạn thông báo một Chủ đề mà bạn không có tài liệu tham khảo được lưu trữ (cũng không quan tâm). Bạn có thể nghĩ về nó như một mẫu đăng ký xuất bản ( wait== đăng ký và notify()== xuất bản). Về cơ bản sử dụng thông báo () bạn đang gửi tin nhắn (thậm chí có thể không nhận được và thông thường bạn không quan tâm).

Để tổng hợp, bạn thường sử dụng sleep()cho wait()đồng bộ hóa thời gian và đồng bộ hóa đa luồng.

Chúng có thể được thực hiện theo cách tương tự trong HĐH cơ bản hoặc hoàn toàn không (vì các phiên bản trước của Java không có đa luồng thực sự; có lẽ một số máy ảo nhỏ cũng không làm như vậy). Đừng quên Java chạy trên máy ảo, vì vậy mã của bạn sẽ được chuyển đổi theo thứ gì đó khác với VM / OS / HW mà nó chạy.


54

Ở đây, tôi đã liệt kê một vài khác biệt quan trọng giữa wait()sleep()phương pháp.
PS: Cũng nhấp vào các liên kết để xem mã thư viện (làm việc nội bộ, chỉ cần chơi xung quanh một chút để hiểu rõ hơn).

chờ đợi()

  1. wait() phương pháp giải phóng khóa.
  2. wait()là phương pháp của Objectlớp.
  3. wait() là phương pháp không tĩnh - public final void wait() throws InterruptedException { //...}
  4. wait()nên được thông báo bằng notify()hoặc notifyAll()phương pháp.
  5. wait() phương thức cần được gọi từ một vòng lặp để xử lý cảnh báo sai.

  6. wait() phương thức phải được gọi từ ngữ cảnh được đồng bộ hóa (tức là phương thức hoặc khối được đồng bộ hóa), nếu không nó sẽ ném IllegalMonitorStateException

ngủ()

  1. sleep() phương pháp không giải phóng khóa.
  2. sleep()là phương pháp của java.lang.Threadlớp.
  3. sleep() là phương thức tĩnh - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. sau khi lượng thời gian quy định, sleep()được hoàn thành.
  5. sleep()tốt hơn không gọi từ vòng lặp (tức là xem mã dưới đây ).
  6. sleep()có thể được gọi từ bất cứ đâu. không có yêu cầu cụ thể.

Tham chiếu: Sự khác biệt giữa Chờ và Ngủ

Đoạn mã để gọi phương thức chờ và ngủ

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

chuyển đổi chủ đề sang các trạng thái chủ đề khác nhau


Có đúng là một sợi ngủ có thể được đánh thức bằng các cuộc gọi để thông báo () không? Một số bài viết khác ở đây dường như ngụ ý một chủ đề ngủ không thể được đánh thức nhưng bị gián đoạn.
berimbolo

Có, Thread.sleep()được sử dụng để làm cho thời gian xử lý có sẵn cho các luồng khác. thời gian ngủ có thể được chấm dứt bởi các ngắt (tức là bởi JVM). Đọc stackoverflow.com/questions/4264355/
roottraveller

Bài đăng đó cũng nói ngắt () là cái gì đánh thức một sợi ngủ? Tôi đã đề cập đến sơ đồ trạng thái luồng mà bạn đã đăng ở đó thông báo hoặc thông báoTất cả mang một luồng ngủ (không chờ) trở lại để sẵn sàng chạy. Tôi chỉ muốn chắc chắn rằng tôi hiểu điều đó.
berimbolo

@berimbolo notify()hoặc notifyAll()Objectphương pháp lớp. do đó chúng có sẵn sẽ obj của tất cả các lớp (tức là ở đây cũng có Threadlớp). xem mã grepcode.com/file/reposective.grepcode.com/java/root/jdk/openjdk/ Kẻ
roottraveller

2
OK Tôi cần đọc thêm về lập lịch luồng vì tôi không thể tìm thấy các ví dụ về notify () hoặc notifyAll () đánh thức các luồng ngủ chỉ làm gián đoạn () làm điều này. Tất cả các ví dụ liên quan đến thông báo () và notifyAll () cho các luồng đang chờ trên một số đối tượng màn hình.
berimbolo

29

Có một số lưu ý chính khác nhau mà tôi kết luận sau khi làm việc chờ đợi và ngủ, trước tiên hãy xem mẫu bằng cách sử dụng Wait () và ngủ ():

Example1 : sử dụng chờ đợi () và giấc ngủ ():

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

Hãy làm rõ một số lưu ý chính:

  1. Gọi về :
    • Wait (): Gọi trên luồng hiện tại giữ đối tượng HandObject
    • ngủ (): Gọi tác vụ thực thi luồng lấy bia (là phương thức lớp nên ảnh hưởng đến luồng đang chạy)
  2. Đã đồng bộ hóa :
    • Wait (): khi đồng bộ hóa đa luồng truy cập cùng một đối tượng (HandObject) (Khi cần giao tiếp giữa nhiều hơn một luồng (thực thi mã hóa, luồng thực thi lấy bia) truy cập trên cùng một đối tượng HandObject)
    • ngủ (): khi điều kiện chờ tiếp tục thực thi (Chờ bia có sẵn)
  3. Giữ khóa :
    • Wait (): giải phóng khóa để đối tượng khác có cơ hội thực thi (HandObject là miễn phí, bạn có thể thực hiện công việc khác)
    • ngủ (): giữ khóa ít nhất t lần (hoặc cho đến khi bị gián đoạn) (Công việc của tôi vẫn chưa kết thúc, tôi tiếp tục giữ khóa và chờ một số điều kiện để tiếp tục)
  4. Điều kiện thức dậy :
    • chờ (): cho đến khi cuộc gọi thông báo (), notifyAll () từ đối tượng
    • ngủ (): cho đến khi ít nhất là hết thời gian hoặc ngắt cuộc gọi
  5. Và điểm cuối cùng là sử dụng khi như estani chỉ ra:

bạn thường sử dụng chế độ ngủ () để đồng bộ hóa thời gian và chờ () để đồng bộ hóa đa luồng.

Vui long sửa cho tôi nêu tôi sai.


26

Sự khác biệt giữa chờ () và ngủ ()

  • Sự khác biệt cơ bản wait()là từ Objectsleep()là một phương thức tĩnh của Thread.

  • Sự khác biệt chính là wait()giải phóng khóa trong khi sleep()không giải phóng bất kỳ khóa nào trong khi chờ đợi.

  • wait()thường được sử dụng để liên lạc giữa các luồng trong khi thường sleep()được sử dụng để giới thiệu tạm dừng khi thực hiện.

  • wait()nên được gọi từ bên trong đồng bộ hóa hoặc nếu không chúng ta nhận được IllegalMonitorStateException, trong khi sleep() có thể được gọi ở bất cứ đâu.

  • Để bắt đầu một chủ đề một lần nữa từ wait(), bạn phải gọi notify()hoặc notifyAll(). Đối với sleep(),các chủ đề được bắt đầu sau một khoảng thời gian xác định.

Điểm tương đồng

  • Cả hai làm cho chủ đề hiện tại đi vào trạng thái Không thể chạy .
  • Cả hai đều là phương pháp bản địa .

18

Đây là một câu hỏi rất đơn giản, bởi vì cả hai phương pháp này có cách sử dụng hoàn toàn khác nhau.

Sự khác biệt chính là chờ phát hành khóa hoặc màn hình trong khi ngủ không giải phóng bất kỳ khóa hoặc màn hình nào trong khi chờ. Chờ được sử dụng để liên lạc giữa các luồng trong khi chế độ ngủ được sử dụng để giới thiệu tạm dừng khi thực hiện.

Đây chỉ là một lời giải thích rõ ràng và cơ bản, nếu bạn muốn nhiều hơn thế thì hãy tiếp tục đọc.

Trong trường hợp wait()luồng phương thức chuyển sang trạng thái chờ và nó sẽ không tự động quay lại cho đến khi chúng ta gọi notify()phương thức (hoặc notifyAll()nếu bạn có nhiều hơn thì một luồng ở trạng thái chờ và bạn muốn đánh thức tất cả các luồng đó). Và bạn cần đồng bộ hóa hoặc khóa đối tượng hoặc khóa lớp để truy cập wait()hoặc notify()hoặc notifyAll()phương thức. Và một điều nữa, wait()phương thức này được sử dụng để liên lạc giữa các luồng bởi vì nếu một luồng ở trạng thái chờ, bạn sẽ cần một luồng khác để đánh thức luồng đó.

Nhưng trong trường hợp sleep()này, đây là một phương pháp được sử dụng để giữ tiến trình trong vài giây hoặc thời gian bạn muốn. Bởi vì bạn không cần phải kích động bất kỳ notify()hoặc notifyAll()phương pháp nào để lấy lại chủ đề đó. Hoặc bạn không cần bất kỳ chủ đề nào khác để gọi lại chủ đề đó. Giống như nếu bạn muốn điều gì đó sẽ xảy ra sau vài giây như trong một trò chơi sau khi người dùng đến lượt bạn muốn người dùng đợi cho đến khi máy tính chơi thì bạn có thể đề cập đến sleep()phương pháp.

Và một sự khác biệt quan trọng hơn thường được hỏi trong các cuộc phỏng vấn: sleep()thuộc về Threadlớp và wait()thuộc về Objectlớp.

Đây là tất cả sự khác biệt giữa sleep()wait().

Và có một sự tương đồng giữa cả hai phương thức: cả hai đều là câu lệnh được kiểm tra, do đó bạn cần thử bắt hoặc ném để truy cập các phương thức này.

Tôi hy vọng điều này sẽ giúp bạn.


16

nguồn: http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()gửi luồng hiện tại vào trạng thái "Không thể chạy" trong một khoảng thời gian. Luồng giữ cho các màn hình mà nó bị ngấm nước - tức là nếu luồng hiện đang ở trong một khối hoặc phương thức được đồng bộ hóa thì không có luồng nào khác có thể vào khối hoặc phương thức này. Nếu một chủ đề khác gọi t.interrupt()nó sẽ đánh thức các chủ đề ngủ.

Lưu ý rằng ngủ là một phương thức tĩnh, có nghĩa là nó luôn ảnh hưởng đến luồng hiện tại (phương thức đang thực thi phương thức ngủ). Một lỗi phổ biến là gọi t.sleep()trong đó t là một chủ đề khác nhau; thậm chí sau đó, nó là chủ đề hiện tại sẽ ngủ, không phải chủ đề t.

t.suspend()bị phản đối Sử dụng nó có thể dừng một luồng khác với luồng hiện tại. Một chuỗi treo giữ tất cả các màn hình của nó và vì trạng thái này không bị gián đoạn nên nó dễ bị bế tắc.

object.wait()gửi chủ đề hiện tại vào trạng thái "Không thể chạy" , như sleep(), nhưng với một twist. Chờ được gọi trên một đối tượng, không phải là một chủ đề; chúng tôi gọi đối tượng này là "đối tượng khóa." Trước khi lock.wait()được gọi, luồng hiện tại phải đồng bộ hóa trên đối tượng khóa; wait() sau đó giải phóng khóa này và thêm chuỗi vào "danh sách chờ" được liên kết với khóa. Sau đó, một luồng khác có thể đồng bộ hóa trên cùng một đối tượng khóa và gọi lock.notify(). Điều này đánh thức các chủ đề ban đầu, chờ đợi. Về cơ bản, wait()/ notify()giống như sleep()/ interrupt(), chỉ luồng hoạt động không cần con trỏ trực tiếp đến luồng ngủ mà chỉ đối với đối tượng khóa được chia sẻ.


14

Chờ đợi và ngủ là hai điều khác nhau:

  • Trong sleep()luồng ngừng hoạt động trong thời gian quy định.
  • Trong wait()luồng ngừng hoạt động cho đến khi đối tượng đang chờ được thông báo, thường là bởi các luồng khác.

nhưng bạn có thể làm gián đoạn một chủ đề đang ngủ. Trong trường hợp đó, Wait () không bị thừa, nó cũng lãng phí chu kỳ CPU :-(
Geek

9
Chờ không lãng phí chu kỳ CPU.
Peter tibraný

1
@Peter - Tôi nghĩ là có. Nó chờ () cho khối chu kỳ CPU và sau đó HĐH cung cấp chu kỳ CPU cho các Chủ đề khác. Tôi nghĩ rằng điều này có thể phụ thuộc vào hệ điều hành, tôi không chắc chắn.
Geek

3
Sẽ rất kém khi thực hiện Wait () nếu nó lãng phí chu kỳ CPU. chờ / thông báo được sử dụng khá nhiều cho giao tiếp giữa các bên.
Peter tibraný

2
@Pacerier hai cấu trúc được dành cho một mục đích khác nhau. Nếu bạn muốn một luồng dừng trong một khoảng thời gian cố định bạn sử dụng sleep, nếu bạn muốn nó dừng lại cho đến khi một số đầu vào đến từ đầu kia bạn sử dụng wait/ notify. interruptđược dự định như một cách để báo hiệu một luồng rằng nó sẽ ngừng làm những gì nó đang làm và chấm dứt. Nó được xử lý bởi sleep, waitnhưng cũng chặn các hàm I / O (và bạn có thể thực hiện các hàm có cùng hành vi bằng cách gọi phương thức Thread.interrupted()). Về hiệu suất, các chức năng thường được tối ưu hóa cho mục tiêu mà chúng được thiết kế.
pqnet

11

sleeplà một phương thức Thread, waitlà một phương thức Object, cũng wait/notifylà một kỹ thuật đồng bộ hóa dữ liệu được chia sẻ trong Java (sử dụng trình giám sát ), nhưng sleeplà một phương thức đơn giản của luồng để tự tạm dừng.


8

ngủ () là một phương thức được sử dụng để giữ tiến trình trong vài giây hoặc thời gian bạn muốn nhưng trong trường hợp luồng phương thức Wait () chuyển sang trạng thái chờ và nó sẽ không tự động quay lại cho đến khi chúng ta gọi thông báo () hoặc thông báoTất cả ().

Sự khác biệt chínhWait () giải phóng khóa hoặc màn hình trong khi ngủ () không giải phóng bất kỳ khóa hoặc màn hình nào trong khi chờ. Nói chung, Wait được sử dụng để liên lạc giữa các luồng trong khi chế độ ngủ được sử dụng để giới thiệu tạm dừng khi thực thi.

Thread.s ngủ () sẽ gửi chủ đề hiện tại vào trạng thái Hiện tại không chạy được trong một số thời gian. Chuỗi giữ cho các màn hình mà nó thu được - tức là nếu luồng hiện đang ở trong một khối hoặc phương thức được đồng bộ hóa thì không có luồng nào khác có thể vào khối hoặc phương thức này. Nếu một luồng khác gọi t.interrupt () thì nó sẽ đánh thức luồng ngủ. Lưu ý rằng ngủ là một phương thức tĩnh, có nghĩa là nó luôn ảnh hưởng đến luồng hiện tại (phương thức đang thực thi phương thức ngủ). Một lỗi phổ biến là gọi t.s ngủ () trong đó t là một luồng khác nhau; thậm chí sau đó, nó là chủ đề hiện tại sẽ ngủ, không phải chủ đề t.

object.wait () gửi luồng hiện tại vào trạng thái không chạy Run , như ngủ (), nhưng với một nút xoắn. Chờ được gọi trên một đối tượng, không phải là một chủ đề; chúng tôi gọi đối tượng này là đối tượng khóa. Trước khi lock.wait () được gọi, luồng hiện tại phải đồng bộ hóa trên đối tượng khóa; Wait () sau đó phát hành khóa này và thêm chủ đề vào danh sách chờ đợi của Google được liên kết với khóa. Sau đó, một luồng khác có thể đồng bộ hóa trên cùng một đối tượng khóa và gọi lock.notify (). Điều này đánh thức các chủ đề ban đầu, chờ đợi. Về cơ bản, Wait () / notify () giống như ngủ () / interrupt (), chỉ có luồng hoạt động không cần con trỏ trực tiếp đến luồng ngủ mà chỉ với đối tượng khóa được chia sẻ.

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}

Hãy phân loại tất cả các điểm trên:

Call on:

  • Wait (): Gọi một đối tượng; luồng hiện tại phải đồng bộ hóa trên đối tượng khóa.
  • ngủ (): Gọi trên một chủ đề; luôn luôn thực hiện chủ đề.

Synchronized:

  • Wait (): khi được đồng bộ hóa nhiều luồng truy cập cùng một đối tượng.
  • ngủ (): khi nhiều chủ đề được đồng bộ hóa chờ ngủ qua chủ đề ngủ.

Hold lock:

  • Wait (): nhả khóa để các đối tượng khác có cơ hội thực thi.
  • ngủ (): giữ khóa ít nhất t lần nếu hết thời gian chỉ định hoặc ai đó bị gián đoạn.

Wake-up condition:

  • chờ (): cho đến khi cuộc gọi thông báo (), notifyAll () từ đối tượng
  • ngủ (): cho đến khi ít nhất là hết thời gian hoặc gọi ngắt ().

Usage:

  • ngủ (): để đồng bộ hóa thời gian và;
  • Wait (): để đồng bộ hóa đa luồng.

Tham chiếu: khác biệt sleepwait


6

Nói một cách đơn giản, chờ đợi là chờ đợi Cho đến khi một số luồng khác gọi bạn trong khi giấc ngủ "không thực hiện câu lệnh tiếp theo" trong một khoảng thời gian xác định.

Hơn nữa, ngủ là phương thức tĩnh trong lớp Thread và nó hoạt động trên luồng, trong khi Wait () nằm trong lớp Object và được gọi trên một đối tượng.

Một điểm khác, khi bạn gọi chờ trên một đối tượng nào đó, luồng liên quan sẽ đồng bộ hóa đối tượng và sau đó chờ. :)


1
Tại sao bạn cần cả hai? Tại sao ngủ () không đủ?
Geek

2
Thông báo được sử dụng để liên lạc giữa các chủ đề. Để gọi chờ, bạn cần một số đối tượng, đồng bộ hóa trên đó và sau đó gọi chờ trên đó. Để được thông báo, bạn cần luồng khác để đồng bộ hóa trên cùng một đối tượng và gọi thông báo.
Peter tibraný

6

waitsleepphương pháp rất khác nhau:

  • sleep không có cách "thức dậy",
  • trong khi đó waitcó một cách "thức dậy" trong thời gian chờ đợi, bằng cách gọi một luồng khác notifyhoặc notifyAll.

Hãy suy nghĩ về nó, những cái tên khó hiểu trong khía cạnh đó; tuy nhiên sleeplà một tên tiêu chuẩn và waitgiống như WaitForSingleObjecthoặc WaitForMultipleObjectstrong API Win.


3
Nhưng chúng ta có thể làm gián đoạn một giấc ngủ không? Vì vậy, sự khác biệt với giấc ngủ / gián đoạn so với chờ đợi / thông báo là gì?
Pacerier

2
Bạn có thể làm gián đoạn một người đang ngủ, nhưng bạn chỉ có thể thông báo cho một người đang chờ. Chủ đề là như nhau.
Rishi

5

Từ bài đăng này: http://javaconceptoftheday.com/difference-b between -wait-and-s ngủ-method-in-java /

chờ () Phương thức.

1) Chủ đề gọi phương thức Wait () giải phóng khóa mà nó giữ.

2) Chuỗi lấy lại khóa sau khi các luồng khác gọi các phương thức notify () hoặc notifyAll () trên cùng một khóa.

3) phương thức Wait () phải được gọi trong khối được đồng bộ hóa.

4) phương thức Wait () luôn được gọi trên các đối tượng.

5) Các luồng chờ có thể được đánh thức bởi các luồng khác bằng cách gọi các phương thức notify () hoặc notifyAll ().

6) Để gọi phương thức Wait (), luồng phải có khóa đối tượng.

phương pháp ngủ ()

1) Chuỗi gọi phương thức ngủ () không giải phóng khóa mà nó giữ.

2) phương thức ngủ () có thể được gọi trong hoặc ngoài khối được đồng bộ hóa.

3) phương thức ngủ () luôn được gọi trên các chủ đề.

4) Các chủ đề ngủ không thể được đánh thức bởi các chủ đề khác. Nếu làm như vậy, luồng sẽ ném Interrupttedception.

5) Để gọi phương thức ngủ (), luồng không cần phải có khóa đối tượng.


4

Ở đây, Wait () sẽ ở trạng thái chờ cho đến khi nó thông báo bởi một Thread khác, nhưng khi ngủ () sẽ có lúc .. sau đó nó sẽ tự động chuyển sang trạng thái Sẵn sàng ...


4
  1. wait()là một phương pháp của Objectlớp.
    sleep()là một phương pháp của Threadlớp.

  2. sleep()cho phép luồng đi đến sleeptrạng thái trong x mili giây.
    Khi một chủ đề đi vào trạng thái ngủ it doesn’t release the lock.

  3. wait()cho phép chủ đề để phát hành khóa và goes to suspended state.
    Chuỗi này sẽ hoạt động khi một notify()hoặc một notifAll()phương thức được gọi cho cùng một đối tượng.


4

Một sự khác biệt lớn tiềm năng giữa giấc ngủ / gián đoạn và chờ đợi / thông báo là

Tạo một ngoại lệ khi không cần thiết là không hiệu quả. Nếu bạn có các luồng giao tiếp với nhau ở tốc độ cao, thì nó sẽ tạo ra rất nhiều ngoại lệ nếu bạn gọi ngắt liên tục, điều này gây lãng phí toàn bộ CPU.


+1, Một điểm hợp lệ thực sự, mặc dù tranh luận về nội bộ của việc triển khai có thể phù hợp hơn với phân tích hiệu suất ...
Pacerier

Nói cách khác, chi phí tạo ngoại lệ có thể nhỏ hơn đáng kể so với chi phí thực hiện của hệ thống so với bên kia.
Pacerier

3

Bạn đã đúng - Ngủ () làm cho luồng đó "ngủ" và CPU sẽ tắt và xử lý các luồng khác (còn được gọi là chuyển đổi ngữ cảnh) tôi tin rằng Wait giữ CPU xử lý luồng hiện tại.

Chúng tôi có cả hai vì mặc dù có vẻ hợp lý khi cho phép người khác sử dụng CPU trong khi bạn không sử dụng nó, nhưng thực tế có một chi phí chuyển đổi ngữ cảnh - tùy thuộc vào thời gian ngủ là bao lâu, nó có thể tốn kém hơn trong chu kỳ CPU để chuyển đổi chủ đề hơn là chỉ đơn giản là chủ đề của bạn không làm gì trong vài ms.

Cũng lưu ý rằng giấc ngủ buộc một chuyển đổi bối cảnh.

Ngoài ra - nói chung, không thể kiểm soát chuyển đổi ngữ cảnh - trong thời gian Chờ hệ điều hành có thể (và sẽ chờ đợi lâu hơn) chọn xử lý các luồng khác.


4
chờ () không giữ CPU xử lý luồng hiện tại. Nó giống như giấc ngủ ở chỗ nó cũng gây ra chuyển đổi ngữ cảnh: javamex.com/tutorials/threads/context_switch.shtml . Tôi đã yêu cầu nửa năm xung quanh stackoverflow và dường như không ai biết sự khác biệt giữa chờ đợi / thông báo so với ngủ / gián đoạn.
Pacerier

Mặc dù giấc ngủ không giữ CPU xử lý luồng hiện tại, tôi nghĩ, dù sao nó cũng là một gánh nặng cho CPU, bởi vì CPU cần theo dõi thời điểm khi nào kết thúc giấc ngủ. Nó không có kích hoạt bên ngoài như "thông báo" trong chờ đợi. Không?
Vladimir Nabokov

@VladimirNabokov, Kích hoạt bên ngoài là interrupt. Thời gian kết thúc là ntrong wait(n). Đã 8 năm rồi mà vẫn không có ai có câu trả lời!
Pacerier

3

Các phương pháp được sử dụng cho những thứ khác nhau.

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.s ngủ (n) thể bị gián đoạn, nhưng Object.wait () phải được thông báo. Có thể chỉ định thời gian chờ tối đa: Object.wait(5000)vì vậy có thể sử dụng waitđể, er,sleep nhưng sau đó bạn phải bận tâm với khóa.

Cả hai phương pháp đều không sử dụng cpu khi ngủ / chờ.

Các phương thức được thực hiện bằng mã gốc, sử dụng các cấu trúc tương tự nhưng không theo cùng một cách.

Hãy tự tìm kiếm: Mã nguồn của các phương thức gốc có sẵn không? Tập tin /src/share/vm/prims/jvm.cpplà điểm khởi đầu ...


Thời gian Thread.s ngủ cũng có thể được đặt thành không xác định. Object.wait thời gian cũng có thể được đặt thành xác định. Câu trả lời này không giải thích được tại sao chúng ta cần 2 cái búa làm điều tương tự.
Pacerier

Thread.sleep(big_num) phải bị gián đoạn. Object.wait(small_num) có thể được thông báo
Pacerier

3

Chờ () và ngủ () Sự khác biệt?

Thread.s ngủ () Sau khi công việc của nó hoàn thành thì chỉ phát hành khóa cho mọi người. cho đến khi nó không bao giờ phát hành khóa cho bất cứ ai.

  Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

Object.wait () Khi đến giai đoạn chờ, nó sẽ phát hành khóa và chờ trong vài giây dựa trên tham số.

Ví dụ:

bạn đang cầm ly cà phê trong tay phải của mình, bạn có thể lấy một người khác cùng bàn tay, khi nào bạn đặt xuống thì chỉ lấy một vật khác cùng loại ở đây. cũng thế. Đây là giấc ngủ () bạn ngủ thời gian bạn không làm việc gì, bạn chỉ đang ngủ .. cũng ở đây.

chờ đợi(). Khi bạn được đặt xuống và có nghĩa là một trong khi bạn đang chờ đợi, đó là chờ đợi

bạn đang chơi phim hoặc bất cứ thứ gì trong hệ thống của bạn giống như trình phát bạn không thể phát nhiều lần cùng một lúc, đó là ở đây, khi bạn đóng và chọn bất kỳ ai khác có nghĩa là phim hoặc bài hát trong khi được gọi là chờ


3

waitphát hành khóa và sleepkhông. Một chuỗi trong trạng thái chờ đủ điều kiện để thức dậy ngay khi notifyhoặc notifyAllđược gọi. Nhưng trong trường hợp sleepluồng giữ khóa và nó sẽ chỉ đủ điều kiện khi hết thời gian ngủ.


Vậy nếu sợi chỉ ngủ trong 10 giây và một ngoại lệ bị gián đoạn xảy ra ????
Geek

@Geek An InterruptedExceptionbị ném, giống như nó nói trong Javadoc.
Hầu tước Lorne

@EJP: Bạn có phải là cùng EJP đã tham gia diễn đàn sun.java.com không? Toàn bộ số điểm của bạn cho thấy tương tự :-)
Geek

2

sleep()phương thức làm cho luồng hiện tại chuyển từ trạng thái chạy sang trạng thái chặn trong một thời gian xác định. Nếu luồng hiện tại có khóa của bất kỳ đối tượng nào thì nó vẫn giữ nó, điều đó có nghĩa là các luồng khác không thể thực thi bất kỳ phương thức được đồng bộ hóa nào trong đối tượng lớp đó.

wait() phương thức làm cho luồng hiện tại đi vào trạng thái khối trong một thời gian xác định hoặc cho đến khi thông báo, nhưng trong trường hợp này, luồng giải phóng khóa của đối tượng (có nghĩa là các luồng khác có thể thực hiện bất kỳ phương thức đồng bộ hóa nào của đối tượng gọi.


2

Theo tôi, sự khác biệt chính giữa cả hai cơ chế là ngủ / ngắt là cách xử lý các luồng cơ bản nhất, trong khi chờ đợi / thông báo là một sự trừu tượng nhằm thực hiện giao tiếp giữa các luồng dễ dàng hơn.Điều này có nghĩa là giấc ngủ / gián đoạn có thể làm bất cứ điều gì, nhưng nhiệm vụ cụ thể này khó thực hiện hơn.

Tại sao chờ đợi / thông báo phù hợp hơn? Dưới đây là một số cân nhắc cá nhân:

  1. Nó thi hành tập trung. Nó cho phép phối hợp giao tiếp giữa một nhóm các luồng với một đối tượng chia sẻ duy nhất. Điều này đơn giản hóa công việc rất nhiều.

  2. Nó thực thi đồng bộ hóa. Bởi vì nó làm cho lập trình viên kết thúc cuộc gọi để chờ / thông báo trong một khối được đồng bộ hóa.

  3. Nó độc lập với nguồn gốc và số lượng. Với phương pháp này, bạn có thể thêm nhiều luồng tùy ý mà không cần chỉnh sửa các luồng khác hoặc theo dõi các luồng hiện có. Nếu bạn đã sử dụng chế độ ngủ / gián đoạn, trước tiên, bạn sẽ cần giữ các tham chiếu đến các chủ đề ngủ, sau đó ngắt từng cái một, bằng tay.

Một ví dụ từ đời thực rất tốt để giải thích đây là một nhà hàng cổ điển và phương thức mà nhân viên sử dụng để liên lạc giữa họ: Người phục vụ để các yêu cầu của khách hàng ở một vị trí trung tâm (bảng nút chai, bàn, v.v.), rung chuông và các công nhân từ bếp đến nhận những yêu cầu như vậy. Khi đã có bất kỳ khóa học nào sẵn sàng, nhân viên nhà bếp lại rung chuông để nhân viên phục vụ nhận thức và đưa họ đến khách hàng.


2

Ví dụ về giấc ngủ không phát hành khóa và chờ đợi

Ở đây có hai lớp:

  1. Main : Chứa phương thức chính và hai luồng.
  2. Singleton : Đây là lớp singleton với hai phương thức tĩnh getInstance () và getInstance (boolean isWait).

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

Bây giờ chạy ví dụ này, bạn sẽ nhận được dưới đầu ra:

_instance :null
Both singleton are same

Ở đây các trường hợp Singleton được tạo bởi threadA và threadB là như nhau. Nó có nghĩa là threadB đang đợi bên ngoài cho đến khi threadA phát hành khóa.

Bây giờ thay đổi Singleton.java bằng cách nhận xét Thread.s ngủ (500); phương thức và không ghi chú Singleton. class.wait (500); . Ở đây vì Singleton. Class.wait (500); phương thức threadA sẽ giải phóng tất cả các khóa thu được và di chuyển vào trạng thái của Non Non Runnable, threadB sẽ nhận được thay đổi để nhập vào khối được đồng bộ hóa.

Bây giờ chạy lại:

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

Ở đây, các phiên bản Singleton được tạo bởi threadA và threadB KHÔNG giống nhau do threadB đã thay đổi để nhập vào khối được đồng bộ hóa và sau 500 mili giây threadA bắt đầu từ vị trí cuối cùng của nó và tạo thêm một đối tượng Singleton.


2

Nên được gọi từ khối được đồng bộ hóa: wait() phương thức luôn được gọi từ khối được đồng bộ hóa, tức là wait()phương thức cần khóa màn hình đối tượng trước khi đối tượng được gọi. Nhưng sleep()phương thức có thể được gọi từ khối đồng bộ hóa bên ngoài, tức là sleep()phương thức không cần bất kỳ trình giám sát đối tượng nào.

IllegalMonitorStateException: nếu wait()phương thức được gọi mà không thu được khóa đối tượng hơn IllegalMonitorStateExceptionlà bị ném khi chạy, nhưngsleep() phương thức không bao giờ ném ngoại lệ như vậy.

Thuộc về lớp nào: wait() phương thức thuộc về java.lang.Objectlớp nhưng sleep()phương thức thuộc về java.lang.Threadlớp.

Được gọi trên đối tượng hoặc luồng: wait() phương thức được gọi trên các đối tượng nhưng sleep()phương thức được gọi trên Chủ đề không phải đối tượng.

Trạng thái Ðề tài: khi wait()phương pháp được gọi trên đối tượng, sợi màn hình mà holded đối tượng đi từ chạy để chờ đợi nhà nước và có thể trở về trạng thái Runnable chỉ khi notify()hoặc notifyAll()phương pháp được gọi trên đối tượng đó. Và sau đó lập lịch trình xử lý lịch trình mà luồng đi từ trạng thái chạy sang trạng thái chạy. Khi sleep()được gọi trên luồng, nó chuyển từ trạng thái chạy sang trạng thái chờ và có thể trở về trạng thái có thể chạy khi hết thời gian ngủ.

Khi được gọi từ khối được đồng bộ hóa: khi wait()phương thức được gọi là luồng rời khỏi khóa đối tượng. Nhưngsleep() phương thức khi được gọi từ khối đồng bộ hoặc luồng phương thức không để lại khóa đối tượng.

Để tham khảo thêm


có lẽ là một URL tham chiếu tốt hơn URL đó.
vẽ

2

Từ trang tài liệu oracle về phương thức Wait () của Object:

public final void wait()
  1. Làm cho luồng hiện tại phải đợi cho đến khi một luồng khác gọi notify()phương thức hoặc notifyAll()phương thức cho đối tượng này. Nói cách khác, phương thức này hoạt động chính xác như thể nó chỉ đơn giản thực hiện cuộc gọiwait(0) .
  2. Chủ đề hiện tại phải sở hữu màn hình của đối tượng này. Chuỗi phát hành quyền sở hữu màn hình này và đợi cho đến khi một luồng khác thông báo các luồng đang chờ trên màn hình của đối tượng này thức dậy
  3. gián đoạn và đánh thức giả là có thể
  4. Phương thức này chỉ được gọi bởi một chủ đề là chủ sở hữu màn hình của đối tượng này

Phương pháp này ném

  1. IllegalMonitorStateException - nếu luồng hiện tại không phải là chủ sở hữu màn hình của đối tượng.

  2. InterruptedException- nếu bất kỳ luồng nào làm gián đoạn luồng hiện tại trước hoặc trong khi luồng hiện tại đang chờ thông báo. Trạng thái bị gián đoạn của luồng hiện tại sẽ bị xóa khi ngoại lệ này được ném.

Từ trang tài liệu oracle về phương thức ngủ () của Threadlớp:

public static void sleep(long millis)
  1. Làm cho luồng hiện đang thực thi ngủ (tạm dừng thực thi) trong số mili giây đã chỉ định, tùy thuộc vào độ chính xác và chính xác của bộ định thời và bộ lập lịch hệ thống.
  2. Các chủ đề không mất quyền sở hữu của bất kỳ màn hình.

Phương pháp này ném:

  1. IllegalArgumentException - nếu giá trị của millis là âm

  2. InterruptedException- nếu bất kỳ chủ đề nào đã làm gián đoạn chủ đề hiện tại. Trạng thái bị gián đoạn của luồng hiện tại sẽ bị xóa khi ngoại lệ này được ném.

Sự khác biệt chính khác:

wait()là một phương thức không tĩnh (phương thức cá thể) không giống như phương thức tĩnh sleep()(phương thức lớp).


1

wait()được đưa ra bên trong một phương thức được đồng bộ hóa trong khi sleep()được đưa ra bên trong một phương thức không đồng bộ vì wait()phương thức giải phóng khóa trên đối tượng nhưng sleep()hoặc yield()không giải phóng lock().


sleep()có thể bên trong một synchronizedkhối hoặc phương thức. Trả lời không giải thích gì.
Hầu tước Lorne

1
  • Phương pháp này wait(1000)làm cho luồng hiện tại ngủ tối đa một giây .
    • Một luồng có thể ngủ ít hơn 1 giây nếu nó nhận được cuộc gọi notify()hoặcnotifyAll() phương thức.
  • Cuộc gọi sleep(1000)làm cho luồng hiện tại ngủ chính xác trong 1 giây .
    • Ngoài ra chủ đề ngủ không giữ khóa bất kỳ tài nguyên . Nhưng chờ đợi chủ đề nào.

1
sleep(1000)không đảm bảo ngủ đúng 1 giây. Nó có thể bị gián đoạn trước.
Lucio

1
Những bài viết rất khó hiểu. Tất cả các bài viết khác trên chủ đề này nói rằng một chủ đề ngủ DOES giữ khóa và một chủ đề chờ DOESNT giữ khóa. Tương tự bài đăng với sơ đồ ngụ ý rằng các lệnh gọi thông báo () đánh thức các luồng ngủ nhưng các bài viết khác (và sơ đồ trạng thái luồng) ngụ ý rằng chỉ ngắt () hoặc thời gian chờ trôi qua mới thực hiện việc này. Tôi vừa đặt mua cho mình một bản sao đồng thời java trong thực tế, một thứ mà tôi nên đọc từ lâu rồi!
berimbolo

1

Trên thực tế, tất cả điều này được mô tả rõ ràng trong các tài liệu Java (nhưng tôi nhận ra điều này chỉ sau khi đọc câu trả lời).

http://docs.oracle.com/javase/8/docs/api/index.html :

chờ () - Chủ đề hiện tại phải sở hữu màn hình của đối tượng này. Chủ đề giải phóng quyền sở hữu của màn hình này và đợi cho đến khi một luồng khác thông báo các luồng đang chờ trên màn hình của đối tượng này để đánh thức thông qua một cuộc gọi đến phương thức thông báo hoặc phương thức notifyAll. Sau đó, luồng sẽ đợi cho đến khi nó có thể lấy lại quyền sở hữu màn hình và tiếp tục thực thi.

ngủ () - Làm cho luồng hiện đang thực thi ngủ (tạm thời ngừng thực thi) trong số mili giây đã chỉ định, tùy thuộc vào độ chính xác và chính xác của bộ định thời và bộ lập lịch hệ thống. Các chủ đề không mất quyền sở hữu của bất kỳ màn hình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.