Perbedaan antara menunggu () dan tidur ()

1204

Apa perbedaan antara a wait()dan sleep()di Thread?

Apakah pemahaman saya bahwa wait()Thread a -ing masih dalam mode berjalan dan menggunakan siklus CPU tetapi a sleep()-ing tidak mengkonsumsi siklus CPU yang benar?

Mengapa kita memiliki keduanya wait() dan sleep(): bagaimana implementasinya bervariasi di tingkat yang lebih rendah?

Kutu buku
sumber
50
pertanyaan yang sangat bagus semantik keduanya mudah membingungkan.
Andreas Petersson
1
Pertanyaan yang sangat bagus tetapi mereka 2 dalam satu. Mengapa kita memiliki keduanya tidak sama dengan bagaimana mereka dapat (dan tidak!) Diimplementasikan pada tingkat yang lebih rendah. Saya sudah menjawabnya juga.
estani
Misalkan utas A berada di blok yang disinkronkan, dan sementara itu dalam cpu dari utas ini diambil dan diberikan ke utas lain B. sekarang di mana utas A akan pergi, apakah utas lain menunggu di blok yang disinkronkan ini masuk sekarang ?
Peter
1
Berikut ini adalah artikel bagus yang menggambarkannya: qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man
3
justru sebaliknya - sleep "menggunakan" semua siklus CPU yang tersedia, tetapi karena utasnya akan berada di "MENUNGGU" - keadaan ini dapat dihasilkan jika perlu - pada kenyataannya sebagian besar sistem operasi secara otomatis menghasilkan siklus JIKA memungkinkan, karenanya utas Anda tidak akan membuat CPU-load yang sebenarnya ... itu akan melakukannya pada sistem operasi yang lebih lama. Object.wait (), di sisi lain TIDAK PERNAH menggunakan siklus apa pun (sementara tidak diketahui) karena itu diwujudkan melalui perangkat lunak-interupsi dalam banyak kasus - kunci pribadi, sementara & transparan, dilaksanakan oleh JVM. Thread.sleep adalah praktik yang buruk.
khusus

Jawaban:

838

A waitdapat "dibangunkan" oleh utas lainnya yang memanggil notifymonitor yang sedang menunggu sedangkan yang sleeptidak bisa. Juga wait(dan notify) harus terjadi pada blok synchronizedpada objek monitor sedangkan sleeptidak:

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

Pada titik ini utas yang saat ini dijalankan menunggu dan melepaskan monitor . Utas lain mungkin berhasil

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

(pada monobjek yang sama ) dan utas pertama (dengan asumsi itu adalah satu-satunya utas yang menunggu di monitor) akan bangun.

Anda juga dapat menelepon notifyAlljika lebih dari satu utas menunggu pada monitor - ini akan membangunkan semuanya . Namun, hanya satu utas yang akan dapat meraih monitor (ingat bahwa waitada dalam asynchronized blok) dan melanjutkan - yang lainnya kemudian akan diblokir sampai mereka dapat memperoleh kunci monitor.

Hal lain adalah bahwa Anda menelepon waitpada Objectdirinya sendiri (yaitu Anda menunggu di monitor obyek) sedangkan Anda menelepon sleepdi Thread.

Namun titik lain adalah bahwa Anda bisa mendapatkan wakeups palsu dari wait(yaitu benang yang menunggu resume tanpa alasan yang jelas). Anda harus selalu waitberputar sementara pada beberapa kondisi sebagai berikut:

synchronized {
    while (!condition) { mon.wait(); }
}
oxbow_lakes
sumber
131
Tidak, tidak bisa. Itu hanya bisa terganggu.
Peter Štibraný
9
Saat Anda menyela, Anda harus tahu utas mana yang ingin Anda sela. Saat Anda menelepon notifikasi, Anda hanya perlu objek, dan Anda tidak peduli apakah ada utas lain yang 'menunggu' pada objek ini. tunggu / beri tahu digunakan untuk komunikasi, sedangkan tidur digunakan untuk, ehm, tidur.
Peter Štibraný
28
@Geek - mengapa Anda mengatakan tunggu () menghabiskan siklus CPU?
Robert Munteanu
25
Gangguan dimaksudkan sebagai mekanisme untuk dengan lembut mendorong utas untuk berhenti berjalan sepenuhnya dan membatalkan operasi yang tersisa. waitSaya notifybiasanya digunakan untuk menunggu utas lainnya menyelesaikan tugas, atau menunggu hingga kondisi tertentu terpenuhi.
Louis Wasserman
13
Saya membaca semua jawaban tetapi saya masih merasakan sedikit informasi yang hilang. Banyak orang menuliskan definisi dari Javadoc dan juga arti dari dua kata bahasa Inggris tapi saya tidak mengerti. Mengapa saya harus menggunakan sleep daripada menunggu? Apa perbedaan antara pembandingan dan kecepatan? Jika saya dapat melakukan semua yang dapat saya lakukan dengan tidur, mengapa saya harus memilih tidur?
Balazs Zsoldos
334

Satu perbedaan kunci yang belum disebutkan adalah bahwa saat tidur Thread tidak melepaskan kunci yang dimilikinya, sementara menunggu melepaskan kunci pada objek yang wait()dipanggil.

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


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}
Robert Munteanu
sumber
105
Menunggu hanya melepaskan kunci untuk objek yang Anda panggil tunggu () aktif. Itu tidak melepaskan kunci lain .
Jon Skeet
16
Anda sebenarnya tidak perlu memanggil tidur dari dalam kunci - mengunci dan menunggu / memberi tahu berjalan seiring tetapi kunci dan tidur tidak terkait.
oxbow_lakes
7
@oxbow_lakes - Saya akan mengatakan bahwa Anda tidak boleh tidur dengan kunci, ada beberapa kasus penggunaan untuk itu. Hanya ingin menunjukkan perbedaannya.
Robert Munteanu
5
@RobertMunteanu, Jawaban Anda menyesatkan mengklaim bahwa sleepmemegang kunci java , tetapi tidak. Untuk memiliki perbandingan yang adil, kami akan membandingkan synchronized(OUTER_LOCK){ Thread.sleep(1000); }dengan synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }dan kami dapat melihat bahwa kedua instruksi tidak merilis OUTER_LOCK. Jika ada perbedaan, kita dapat mengatakan bahwa sleepitu tidak secara eksplisit menggunakan kunci java , tetapi pertanyaannya adalah tentang kutipan "bagaimana implementasinya bervariasi pada tingkat yang lebih rendah?" tanda kutip.
Pacerier
2
@Pacerier wait()dikaitkan dengan kondisi kunci paling dalam yang dipanggilnya, dalam contoh kode Anda, wait()hanya dapat dilepaskan LOCKdan tidak OUTER_LOCK. Begitulah monitor Java dirancang. Perbandingan yang adil adalah synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }dan synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. Dalam hal ini sleep()akan memegang kedua kunci sementara wait()akan melepaskan LOCKtetapi masih menahanOUTER_LOCK
danze
244

Saya menemukan posting ini bermanfaat. Ini menempatkan perbedaan antara Thread.sleep(), Thread.yield()dan Object.wait()dalam istilah manusia. Kutipan:

Itu semua akhirnya membuat jalan ke penjadwal OS, yang membagikan rentang waktu untuk proses dan utas.

sleep(n)mengatakan, "Aku sudah selesai dengan kutu waktu, dan tolong jangan beri aku yang lain untuk setidaknya n milidetik." OS bahkan tidak mencoba menjadwalkan utas tidur sampai waktu yang diminta berlalu.

yield()mengatakan, "Aku sudah selesai dengan kutu waktu, tapi aku masih punya pekerjaan yang harus dilakukan." OS bebas untuk segera memberi utas kutu waktu lain, atau untuk memberikan utas lain atau memproses CPU yang hanya menyerah.

wait()mengatakan “Aku sudah selesai dengan kutu waktu saya. Jangan beri saya kutu waktu lagi sampai seseorang memanggil notifikasi (). ” Seperti halnya sleep(), OS bahkan tidak akan mencoba untuk menjadwalkan tugas Anda kecuali seseorang memanggilnotify() (atau salah satu dari beberapa skenario bangun lainnya terjadi).

Utas juga kehilangan sisa kutu waktu mereka ketika melakukan pemblokiran IO dan dalam beberapa keadaan lainnya. Jika sebuah thread bekerja melalui seluruh kutu waktu, OS secara paksa mengambil kendali secara kasar seolah-olahyield() telah dipanggil, sehingga proses lain dapat berjalan.

Anda jarang membutuhkannya yield(), tetapi jika Anda memiliki aplikasi yang sangat berat dengan batasan tugas logis, menyisipkan yield() mungkin meningkatkan respons sistem (dengan mengorbankan waktu - sakelar konteks, bahkan hanya untuk OS dan kembali, tidak gratis). Ukur dan uji terhadap sasaran yang Anda pedulikan, seperti biasa.

E-rich
sumber
Yield pada dasarnya tergantung pada platform ... javamex.com/tutorials/threads/yield.shtml
Pacerier
Penjelasan sleep(n)secara implisit mengatakan bahwa utas yang saat ini berjalan melepaskan monitor kunci secara sukarela, yang tidak benar . Kutipan dari Thread's javadoc : "Thread tidak kehilangan kepemilikan monitor apa pun."
Clint Eastwood
2
@ Jonathan tidak ada menyebutkan monitor dalam jawabannya, dan itu karena sleeptidak memiliki perilaku khusus mengenai monitor daripada panggilan metode Java lainnya, yaitu, ia tidak berinteraksi atau memodifikasinya dengan cara apa pun. Jika Anda akan mengatakan sesuatu tentang monitor, Anda harus menentukan bahwa wait, selain hal-hal yang disebutkan di atas, untuk sementara waktu melepaskan kunci pada objek yang dipanggil.
pqnet
Bagaimana cara kerja notifikasi di tingkat scheduler OS? Apakah memberi tahu memanggil semacam pengendali acara dengan id utas tertentu, yang memungkinkan penjadwal untuk mengembalikan utas yang relevan pada antrian yang sedang berjalan? Saya juga punya pertanyaan lain, di manakah konsep spinlock cocok? Apakah hanya relevan untuk tidur atau menunggu sendiri menggunakan spinlock pada tingkat yang sangat rendah?
CMCDragonkai
@Erich, Gunakan wait(n)untuk membandingkan sleep(n). Tidak ada gunanya membandingkan menggunakan no-arg satu.
Pacerier
68

Ada banyak jawaban di sini tetapi saya tidak dapat menemukan perbedaan semantik yang disebutkan di atas.

Ini bukan tentang utas itu sendiri; kedua metode diperlukan karena mereka mendukung kasus penggunaan yang sangat berbeda.

sleep()mengirim Thread ke mode sleep seperti sebelumnya, itu hanya mengemas konteks dan berhenti mengeksekusi untuk waktu yang telah ditentukan. Jadi untuk membangunkannya sebelum batas waktu, Anda perlu mengetahui referensi Thread. Ini bukan situasi umum di lingkungan multi-utas. Ini sebagian besar digunakan untuk sinkronisasi waktu (misalnya bangun tepat 3,5 detik) dan / atau keadilan hard-kode (hanya tidur sebentar dan biarkan thread lain bekerja).

wait(), sebaliknya, adalah mekanisme sinkronisasi utas (atau pesan) yang memungkinkan Anda memberi tahu utas yang tidak memiliki referensi tersimpan (atau peduli). Anda dapat menganggapnya sebagai pola terbitkan-berlangganan ( wait== berlangganan dannotify() == terbitkan). Pada dasarnya menggunakan notify () Anda mengirim pesan (yang bahkan mungkin tidak diterima sama sekali dan biasanya Anda tidak peduli).

Singkatnya, Anda biasanya menggunakan sleep()sinkronisasi waktu dan sinkronisasi wait()multi-utas.

Mereka dapat diimplementasikan dengan cara yang sama di OS yang mendasarinya, atau tidak sama sekali (karena versi Java sebelumnya tidak memiliki multithreading nyata; mungkin beberapa VM kecil tidak melakukan itu juga). Jangan lupa Java berjalan pada VM, jadi kode Anda akan ditransformasikan dalam sesuatu yang berbeda sesuai dengan VM / OS / HW yang dijalankannya.

estani
sumber
54

Di sini, saya telah membuat daftar beberapa perbedaan penting antara wait()dan sleep()metode.
PS: Juga klik tautan untuk melihat kode perpustakaan (internal bekerja, hanya bermain-main sedikit untuk pemahaman yang lebih baik).

Tunggu()

  1. wait() Metode melepaskan kunci.
  2. wait()adalah metode Objectkelas.
  3. wait() adalah metode non-statis - public final void wait() throws InterruptedException { //...}
  4. wait()harus diberitahukan oleh notify()atau notifyAll()metode.
  5. wait() Metode perlu dipanggil dari loop untuk menangani alarm palsu.

  6. wait() Metode harus dipanggil dari konteks yang disinkronkan (yaitu metode atau blok yang disinkronkan), jika tidak ia akan melempar IllegalMonitorStateException

tidur()

  1. sleep() Metode tidak melepaskan kunci.
  2. sleep()adalah metode java.lang.Threadkelas.
  3. sleep() adalah metode statis - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. setelah jumlah waktu yang ditentukan, sleep()selesai.
  5. sleep()lebih baik tidak menelepon dari loop (yaitu lihat kode di bawah ).
  6. sleep()dapat dipanggil dari mana saja. tidak ada persyaratan khusus.

Ref: Perbedaan antara Tunggu dan Tidur

Cuplikan kode untuk metode panggilan menunggu dan tidur

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

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

transisi utas ke status utas berbeda

roottraveller
sumber
Apakah benar bahwa utas tidur dapat dibangunkan oleh panggilan untuk memberi tahu ()? Beberapa posting lain di sini tampaknya menyiratkan utas tidur tidak dapat dibangunkan tetapi terganggu.
berimbolo
Ya, Thread.sleep()digunakan untuk membuat waktu prosesor tersedia untuk utas lainnya. periode tidur dapat diakhiri dengan interupsi (yaitu dengan JVM). Baca ini stackoverflow.com/questions/4264355/…
roottraveller
Posting itu juga mengatakan interrupt () adalah apa yang membangunkan thread tidur? Saya merujuk pada diagram status utas yang Anda poskan di mana dikatakan beri tahu atau beri tahuSemua membawa utas tidur (tidak menunggu) kembali ke siap dijalankan. Saya hanya ingin memastikan saya mengerti itu.
berimbolo
@berimbolo notify()atau notifyAll()yang Objectmetode kelas. maka mereka tersedia akan keberatan dari semua kelas (yaitu di sini dengan Threadkelas juga). lihat kode grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller
2
OK saya perlu membaca lebih lanjut tentang penjadwalan utas karena saya tidak dapat menemukan contoh notify () atau notifyAll () membangunkan thread tidur hanya mengganggu () melakukan hal ini. Semua contoh menghubungkan notify () dan notifyAll () ke utas yang menunggu pada beberapa objek monitor.
berimbolo
29

Ada beberapa perbedaan catatan kunci yang saya simpulkan setelah mengerjakan wait and sleep, pertama-tama lihat sampel menggunakan wait () dan sleep ():

Contoh1 : menggunakan wait () dan sleep ():

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();
}

Biarkan kejelasan beberapa catatan utama:

  1. Panggil :
    • wait (): Panggil utas saat ini yang memegang Objek HandObject
    • sleep (): Call on Thread mengeksekusi tugas dapatkan bir (metode kelas sangat memengaruhi thread yang sedang berjalan)
  2. Disinkronkan :
    • wait (): ketika multi-thread disinkronkan mengakses Objek yang sama (HandObject) (Ketika perlu komunikasi antara lebih dari satu utas (ulas eksekusi koding, ulas eksekusi dapatkan bir) akses pada objek yang sama HandObject)
    • sleep (): ketika kondisi menunggu untuk melanjutkan eksekusi (Menunggu bir tersedia)
  3. Tahan kunci :
    • wait (): lepaskan kunci untuk objek lain yang memiliki peluang untuk dieksekusi (HandObject gratis, Anda dapat melakukan pekerjaan lain)
    • sleep (): simpan kunci setidaknya t kali (atau sampai interupsi) (Pekerjaan saya masih belum selesai, saya terus memegang kunci dan menunggu beberapa kondisi untuk melanjutkan)
  4. Kondisi bangun :
    • wait (): sampai call notify (), notifyAll () dari object
    • sleep (): hingga setidaknya waktu kedaluwarsa atau interupsi panggilan
  5. Dan poin terakhir digunakan ketika sebagai estani menunjukkan:

Anda biasanya menggunakan sleep () untuk sinkronisasi waktu dan menunggu () untuk sinkronisasi multi-utas.

Harap perbaiki saya jika saya salah.

NguyenDat
sumber
26

Perbedaan antara menunggu () dan tidur ()

  • Perbedaan mendasar wait()adalah dari Objectdan sleep()merupakan metode statis Thread.

  • Perbedaan utama adalah bahwa wait()melepaskan kunci sementara sleep()tidak melepaskan kunci apa pun saat menunggu.

  • wait()digunakan untuk komunikasi antar utas sementara sleep()digunakan untuk memperkenalkan jeda pada eksekusi, secara umum.

  • wait()harus dipanggil dari dalam sinkronisasi atau kita mendapatkan IllegalMonitorStateException, sementara sleep() dapat dipanggil di mana saja.

  • Untuk memulai utas lagi wait(), Anda harus menelepon notify()atau notifyAll(). Adapun sleep(),utas memulai setelah interval waktu yang ditentukan.

Kesamaan

  • Keduanya membuat utas saat ini masuk ke status Tidak Dapat Diaktifkan .
  • Keduanya adalah metode asli .
Premraj
sumber
18

Ini adalah pertanyaan yang sangat sederhana, karena kedua metode ini memiliki kegunaan yang sama sekali berbeda.

Perbedaan utama adalah menunggu untuk melepaskan kunci atau monitor saat tidur tidak melepaskan kunci atau monitor saat menunggu. Tunggu digunakan untuk komunikasi antar utas sementara tidur digunakan untuk memperkenalkan jeda saat eksekusi.

Ini hanya penjelasan yang jelas dan mendasar, jika Anda menginginkan lebih dari itu maka lanjutkan membaca.

Seandainya wait()metode thread masuk dalam status menunggu dan tidak akan kembali secara otomatis sampai kami memanggil notify()metode (atau notifyAll()jika Anda memiliki lebih dari satu utas dalam status menunggu dan Anda ingin membangunkan semua utas itu). Dan Anda perlu disinkronkan atau objek atau kunci kelas untuk akses wait()atau notify()atau notifyAll()metode. Dan satu hal lagi, yaituwait() metode ini digunakan untuk komunikasi antar-thread karena jika sebuah thread masuk dalam keadaan menunggu Anda akan membutuhkan utas lain untuk membangunkan utas itu.

Tetapi dalam hal sleep()ini adalah metode yang digunakan untuk menahan proses selama beberapa detik atau waktu yang Anda inginkan. Karena Anda tidak perlu memprovokasi metode notify()atau apa pun notifyAll()untuk mendapatkan utas itu kembali. Atau Anda tidak perlu utas lainnya untuk menelepon utas itu. Seperti jika Anda menginginkan sesuatu akan terjadi setelah beberapa detik seperti dalam permainan setelah giliran pengguna, Anda ingin pengguna menunggu hingga komputer diputar maka Anda dapat menyebutkan sleep()metodenya.

Dan satu lagi perbedaan penting yang sering ditanyakan dalam wawancara: sleep()milik Threadkelas dan wait()milik Objectkelas.

Ini semua perbedaan antara sleep()dan wait().

Dan ada kesamaan antara kedua metode: keduanya diperiksa pernyataan sehingga Anda perlu mencoba menangkap atau melempar untuk mengakses metode ini.

Saya harap ini akan membantu Anda.

Vikas Gupta
sumber
16

sumber: http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()mengirimkan utas saat ini ke status "Tidak Dapat Dijalankan" untuk beberapa waktu. Utas menjaga monitor yang telah diperolehnya - yaitu jika utas saat ini berada dalam blok atau metode yang disinkronkan, tidak ada utas lain yang bisa masuk blok atau metode ini. Jika utas lain memanggilnya, t.interrupt()ia akan membangunkan utas tidur.

Perhatikan bahwa tidur adalah metode statis, yang berarti selalu mempengaruhi utas saat ini (salah satu yang menjalankan metode tidur). Kesalahan umum adalah menelepon di t.sleep()mana t adalah utas berbeda; meskipun begitu, itu adalah utas saat ini yang akan tidur, bukan utas.

t.suspend()sudah ditinggalkan. Menggunakannya dimungkinkan untuk menghentikan utas selain utas saat ini. Utas yang ditangguhkan membuat semua monitornya dan karena keadaan ini tidak dapat terputus maka rawan jalan buntu.

object.wait()mengirimkan utas saat ini ke status "Tidak Dapat Dijalankan" , seperti sleep(), tetapi dengan twist. Tunggu dipanggil pada objek, bukan utas; kami menyebut objek ini sebagai "objek kunci." Sebelum lock.wait()dipanggil, utas saat ini harus disinkronkan pada objek kunci; wait() kemudian lepaskan kunci ini, dan tambahkan utas ke "daftar tunggu" yang terkait dengan kunci tersebut. Kemudian, utas lain dapat disinkronkan pada objek dan panggilan kunci yang sama lock.notify(). Ini membangunkan utas menunggu asli. Pada dasarnya, wait()/ notify()seperti sleep()/ interrupt(), hanya utas aktif tidak perlu penunjuk langsung ke utas tidur, tetapi hanya ke objek kunci bersama.

om singh
sumber
14

Tunggu dan tidur adalah dua hal berbeda:

  • Di sleep()utas berhenti bekerja untuk durasi yang ditentukan.
  • Di wait()utas berhenti bekerja sampai objek yang menunggu diberitahukan, umumnya oleh utas lainnya.
Itay Maman
sumber
tetapi Anda dapat mengganggu Thread yang sedang tidur. Dalam kasus menunggu () adalah Infact berlebihan itu limbah siklus CPU terlalu :-(
Geek
9
Tunggu, jangan buang siklus CPU.
Peter Štibraný
1
@ Peter - Saya kira begitu. Ia menunggu () untuk sebagian dari siklus CPU dan kemudian OS memberikan siklus CPU ke Thread lain. Saya pikir ini mungkin tergantung OS, saya tidak yakin.
Geek
3
Akan sangat buruk penerapan wait () jika ia membuang-buang siklus CPU. wait / notify digunakan cukup banyak untuk komunikasi interthread.
Peter Štibraný
2
@Pacerier kedua konstruk tersebut dimaksudkan untuk tujuan yang berbeda. Jika Anda ingin utas berhenti untuk jangka waktu tertentu yang Anda gunakan sleep, jika Anda ingin utas berhenti sampai beberapa masukan datang dari yang lain Anda gunakan wait/ notify. interruptdimaksudkan sebagai cara untuk memberi tanda utas bahwa ia harus berhenti melakukan apa yang dilakukannya dan mengakhiri. Ini ditangani oleh sleep, waittetapi juga memblokir fungsi I / O (dan Anda bisa mengimplementasikan fungsi dengan perilaku yang sama dengan memanggil metodeThread.interrupted() ). Adapun kinerja, fungsi biasanya dioptimalkan untuk tujuan yang dirancang.
pqnet
11

sleepadalah metode Thread, waitadalah metode Object, jadi wait/notifyadalah teknik sinkronisasi data bersama di Jawa (menggunakan monitor ), tetapi sleepmerupakan metode sederhana utas untuk menjeda sendiri.

pvllnspk
sumber
8

sleep () adalah metode yang digunakan untuk menahan proses selama beberapa detik atau waktu yang Anda inginkan tetapi dalam kasus menunggu () utas metode berjalan dalam keadaan menunggu dan tidak akan kembali secara otomatis sampai kami memanggil pemberitahuan () atau beri tahuAll ().

Perbedaan utama adalah bahwa wait () melepaskan kunci atau monitor saat tidur () tidak melepaskan kunci atau monitor apa pun saat menunggu. Tunggu digunakan untuk komunikasi antar utas sementara tidur digunakan untuk memperkenalkan jeda saat eksekusi, secara umum.

Thread.sleep () mengirimkan utas saat ini ke status "Tidak Dapat Dijalankan" untuk beberapa waktu. Utas menjaga monitor yang telah diperolehnya - yaitu jika utas saat ini berada dalam blok atau metode yang disinkronkan, tidak ada utas lain yang bisa memasuki blok atau metode ini. Jika utas lain memanggil t.interrupt () ia akan mengaktifkan utas tidur. Perhatikan bahwa tidur adalah metode statis, yang berarti selalu mempengaruhi utas saat ini (salah satu yang menjalankan metode tidur). Kesalahan umum adalah memanggil t.sleep () di mana t adalah utas yang berbeda; meskipun begitu, itu adalah utas saat ini yang akan tidur, bukan utas.

object.wait () mengirimkan utas saat ini ke status "Tidak Dapat Dijalankan", seperti sleep (), tetapi dengan twist. Tunggu dipanggil pada objek, bukan utas; kami menyebut objek ini sebagai "objek kunci." Sebelum lock.wait () dipanggil, utas saat ini harus disinkronkan pada objek kunci; tunggu () kemudian lepaskan kunci ini, dan tambahkan utas ke "daftar tunggu" yang terkait dengan kunci tersebut. Kemudian, utas lain dapat disinkronkan pada objek kunci yang sama dan panggil kunci. Notify (). Ini membangunkan utas menunggu asli. Pada dasarnya, tunggu () / beri tahu () seperti sleep () / interrupt (), hanya utas aktif tidak perlu penunjuk langsung ke utas tidur, tetapi hanya ke objek kunci bersama.

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

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

Biarkan kategorikan semua poin di atas:

Call on:

  • wait (): Panggil objek; utas saat ini harus disinkronkan pada objek kunci.
  • sleep (): Hubungi Thread; selalu menjalankan utas saat ini.

Synchronized:

  • wait (): ketika beberapa utas yang disinkronkan mengakses Objek yang sama satu per satu.
  • sleep (): ketika beberapa utas disinkronkan menunggu untuk tidur dari utas tidur.

Hold lock:

  • wait (): lepaskan kunci agar benda lain memiliki kesempatan untuk mengeksekusi.
  • sleep (): simpan kunci setidaknya t kali jika batas waktu ditentukan atau seseorang menyela.

Wake-up condition:

  • wait (): sampai call notify (), notifyAll () dari object
  • sleep (): hingga setidaknya waktu kedaluwarsa atau interupsi panggilan ().

Usage:

  • sleep (): untuk sinkronisasi waktu dan;
  • wait (): untuk sinkronisasi multi-utas.

Ref: diff sleepdanwait

Mulai Miranda
sumber
6

Dengan kata sederhana, tunggu adalah menunggu. Sampai beberapa utas lain memanggil Anda, sedangkan tidur adalah "jangan jalankan pernyataan berikutnya" untuk jangka waktu tertentu.

Selain itu tidur adalah metode statis di kelas Thread dan beroperasi di thread, sedangkan wait () ada di kelas Object dan memanggil objek.

Poin lain, ketika Anda memanggil tunggu di beberapa objek, utas yang terlibat menyinkronkan objek dan kemudian menunggu. :)

Ratnesh Maurya
sumber
1
Mengapa Anda membutuhkan keduanya? Mengapa tidur () tidak cukup?
Geek
2
Beritahu digunakan untuk komunikasi antar utas. Untuk memanggil tunggu, Anda memerlukan beberapa objek, sinkronkan di atasnya, lalu panggil tunggu di atasnya. Untuk diberi tahu, Anda perlu utas lainnya untuk melakukan sinkronisasi pada objek yang sama , dan panggil notifikasi.
Peter Štibraný
6

waitdan sleepmetodenya sangat berbeda:

  • sleep tidak memiliki cara "bangun",
  • sedangkan waitmemiliki cara "bangun" selama periode menunggu, dengan panggilan thread lain notifyatau notifyAll.

Kalau dipikir-pikir, nama-nama itu membingungkan dalam hal itu; Namun sleepadalah nama standar dan waitseperti WaitForSingleObjectatau WaitForMultipleObjectsdi Win API.

Roee Adler
sumber
3
Tapi kita bisa mengganggu tidur kan ? jadi apa bedanya dengan sleep / interrupt vs wait / notify?
Pacerier
2
Anda dapat mengganggu orang yang sedang tidur, tetapi Anda hanya dapat memberi tahu orang yang menunggu. Utasnya sama.
Rishi
5

Dari pos ini: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

tunggu () Metode.

1) Utas yang memanggil metode tunggu () melepaskan kunci yang dipegangnya.

2) Utas mendapatkan kembali kunci setelah utas lainnya memanggil metode notify () atau notifyAll () pada kunci yang sama.

3) metode wait () harus dipanggil dalam blok yang disinkronkan.

4) metode menunggu () selalu dipanggil pada objek.

5) Utas tunggu dapat dibangunkan oleh utas lain dengan memanggil metode notify () atau notifyAll ().

6) Untuk memanggil metode wait (), utas harus memiliki kunci objek.

sleep () Metode

1) Thread yang memanggil metode sleep () tidak melepaskan kunci yang dipegangnya.

2) metode sleep () dapat dipanggil di dalam atau di luar blok yang disinkronkan.

3) metode sleep () selalu dipanggil utas.

4) Thread tidur tidak dapat dibangunkan oleh utas lainnya. Jika demikian, utas akan melempar InterruptedException.

5) Untuk memanggil metode sleep (), utas tidak perlu memiliki kunci objek.

pengguna2485429
sumber
4

Sini tunggu () akan berada dalam status menunggu sampai diberitahukan oleh Utas lain tetapi ketika sleep () akan memiliki waktu .. setelah itu akan secara otomatis ditransfer ke status Siap ...

Rakhi Jaligama
sumber
4
  1. wait()adalah metode Objectkelas.
    sleep()adalah metode Threadkelas.

  2. sleep()memungkinkan utas masuk ke sleepstatus selama x milidetik.
    Saat utas masuk ke kondisi tidur it doesn’t release the lock.

  3. wait()memungkinkan utas untuk melepaskan kunci dan goes to suspended state.
    Utas ini akan aktif ketika a notify()atau notifAll()metode dipanggil untuk objek yang sama.

VdeX
sumber
4

Satu perbedaan besar potensial antara tidur / menyela dan menunggu / memberi tahu adalah bahwa

Menghasilkan pengecualian saat tidak diperlukan tidak efisien. Jika Anda memiliki utas berkomunikasi satu sama lain dengan kecepatan tinggi, maka itu akan menghasilkan banyak pengecualian jika Anda menelepon interupsi sepanjang waktu, yang merupakan pemborosan total CPU.

Menandai
sumber
+1, Poin yang valid sebenarnya, meskipun berdebat tentang internal implementasi mungkin lebih relevan untuk analisis kinerja ...
Pacerier
Dengan kata lain, overhead untuk membuat pengecualian mungkin jauh lebih kecil daripada overhead implementasi sistem satu vs yang lain.
Pacerier
3

Anda benar - Sleep () menyebabkan utas itu "tertidur" dan CPU akan padam dan memproses utas lainnya (atau dikenal sebagai pengalihan konteks) sementara saya percaya Tunggu, teruskan CPU memproses utas saat ini.

Kami memiliki keduanya karena walaupun tampaknya masuk akal untuk membiarkan orang lain menggunakan CPU saat Anda tidak menggunakannya, sebenarnya ada overhead untuk pengalihan konteks - tergantung pada berapa lama waktu tidur, itu bisa lebih mahal dalam siklus CPU untuk mengganti utas daripada hanya membuat utas Anda tidak melakukan apa-apa selama beberapa ms.

Juga perhatikan bahwa tidur memaksa saklar konteks.

Juga - secara umum tidak mungkin untuk mengontrol peralihan konteks - selama Tunggu, OS dapat (dan akan menunggu lebih lama) memilih untuk memproses utas lainnya.

Justin
sumber
4
tunggu () tidak membuat CPU memproses utas saat ini. Ini seperti tidur yang menyebabkan perubahan konteks juga: javamex.com/tutorials/threads/context_switch.shtml . Saya telah meminta selama setengah tahun di sekitar stackoverflow dan sepertinya tidak ada yang tahu apa perbedaan antara menunggu / memberi tahu vs tidur / menyela.
Pacerier
meskipun tidur tidak membuat CPU dalam memproses thread saat ini, saya pikir, itu sedikit beban bagi CPU, karena CPU perlu melacak saat kapan harus mengakhiri tidur. Itu tidak memiliki pemicu eksternal seperti "memberitahukan" dalam menunggu. Tidak?
Vladimir Nabokov
@VladimirNabokov, Pemicu eksternal adalah interrupt. Waktu berakhir adalah ndi wait(n). ¶¶ Sudah 8 tahun sekarang dan masih belum ada yang menjawab!
Pacerier
3

Metode ini digunakan untuk hal-hal yang berbeda.

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

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

Thread.sleep (n) dapat diinterupsi, tetapi Object.wait () harus diberi tahu. Dimungkinkan untuk menentukan waktu maksimum untuk menunggu: Object.wait(5000)jadi mungkin akan digunakan waituntuk, er, sleeptetapi kemudian Anda harus repot dengan kunci.

Tak satu pun dari metode menggunakan cpu saat tidur / menunggu.

Metode diimplementasikan menggunakan kode asli, menggunakan konstruksi yang sama tetapi tidak dengan cara yang sama.

Cari sendiri: Apakah kode sumber metode asli tersedia? File /src/share/vm/prims/jvm.cppadalah titik awal ...

KarlP
sumber
Thread.sleep tidur juga dapat diatur ke tidak terbatas. Object.wait timing juga dapat diatur ke pasti. Jawaban ini tidak menjelaskan mengapa kita membutuhkan 2 palu yang melakukan hal yang sama.
Pacerier
Thread.sleep(big_num) harus disela. Object.wait(small_num) dapat diberitahukan.
Pacerier
3

Tunggu () dan tidur () Perbedaan?

Thread.sleep () Setelah pekerjaan selesai maka hanya lepaskan kunci untuk semua orang. sampai tidak pernah melepaskan kunci ke siapa pun.

  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 () Ketika akan menunggu tahap, itu akan melepaskan kunci dan menunggu beberapa detik berdasarkan parameter.

Sebagai contoh:

Anda mengambil kopi di tangan kanan Anda, Anda dapat mengambil orang lain dari tangan yang sama, kapan Anda meletakkannya kemudian hanya mengambil objek lain jenis yang sama di sini. juga. ini adalah sleep () Anda waktu tidur Anda tidak bekerja, Anda hanya melakukan tidur .. sama di sini juga.

Tunggu(). ketika Anda diletakkan dan mengambil satu lagi berarti ketika Anda sedang menunggu, itu menunggu

Anda sedang memutar film atau apapun dalam sistem Anda sama dengan pemain Anda tidak dapat bermain lebih dari satu pada waktu yang tepat, itu ada di sini, ketika Anda menutup dan memilih film atau lagu siapa pun yang lain sementara disebut tunggu

VISALIG
sumber
3

waitmelepaskan kunci dan sleeptidak. Utas dalam keadaan menunggu memenuhi syarat untuk bangun segera notifyatau notifyAlldipanggil. Tetapi seandainya sleeputas menjaga kunci dan hanya akan memenuhi syarat setelah waktu tidur selesai.

shikjohari
sumber
Jadi jika utasnya tidur selama 10 detik dan pengecualian yang terputus terjadi ????
Geek
@ Geek An InterruptedExceptionterlempar, seperti yang tertulis di Javadoc.
Marquis of Lorne
@ EJP: Apakah Anda EJP yang sama yang berada di forum sun.java.com? Setidaknya skor Anda menunjukkan hal yang sama :-)
Geek
2

sleep()Metode menyebabkan utas saat ini untuk beralih dari status berjalan ke status blok selama waktu tertentu. Jika utas saat ini memiliki kunci dari objek apa pun maka terus menahannya, yang berarti bahwa utas lain tidak dapat menjalankan metode yang disinkronkan dalam objek kelas itu.

wait() metode menyebabkan utas saat ini masuk ke status blok baik untuk waktu yang ditentukan atau sampai memberitahukan, tetapi dalam kasus ini utas melepaskan kunci objek (yang berarti bahwa utas lain dapat menjalankan metode yang disinkronkan dari objek panggilan.

User10001
sumber
2

Menurut pendapat saya, perbedaan utama antara kedua mekanisme adalah bahwa sleep / interrupt adalah cara paling dasar untuk menangani thread, sedangkan wait / notify adalah abstraksi yang bertujuan untuk melakukan inter-komunikasi thread dengan lebih mudah.Ini berarti bahwa tidur / menyela dapat melakukan apa saja, tetapi tugas khusus ini lebih sulit untuk dilakukan.

Mengapa menunggu / memberi tahu lebih cocok? Berikut ini beberapa pertimbangan pribadi:

  1. Ini menegakkan sentralisasi. Hal ini memungkinkan untuk mengoordinasikan komunikasi antara sekelompok utas dengan satu objek bersama. Ini menyederhanakan banyak pekerjaan.

  2. Ini menegakkan sinkronisasi. Karena itu membuat pemrogram membungkus panggilan untuk menunggu / memberi tahu di blok yang disinkronkan.

  3. Tidak tergantung pada asal dan nomor utas. Dengan pendekatan ini Anda dapat menambahkan lebih banyak utas secara sewenang-wenang tanpa mengedit utas lainnya atau melacak yang sudah ada. Jika Anda menggunakan sleep / interrupt, pertama Anda perlu menyimpan referensi ke thread tidur, dan kemudian menginterupsi mereka satu per satu, dengan tangan.

Contoh dari kehidupan nyata yang baik untuk dijelaskan ini adalah restoran klasik dan metode yang digunakan personel untuk berkomunikasi di antara mereka: Para pelayan meninggalkan permintaan pelanggan di tempat sentral (papan gabus, meja, dll.), membunyikan bel, dan para pekerja dari dapur datang untuk menerima permintaan seperti itu. Setelah ada kursus yang siap, petugas dapur membunyikan bel lagi sehingga para pelayan sadar dan membawa mereka ke pelanggan.

negora
sumber
2

Contoh tentang tidur tidak melepaskan kunci dan menunggu tidak

Di sini ada dua kelas:

  1. Utama : Berisi metode utama dan dua utas.
  2. Singleton : Ini adalah kelas singleton dengan dua metode statis getInstance () dan 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();
    
     }
    }

dan

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;

 }
}

Sekarang jalankan contoh ini Anda akan mendapatkan output di bawah ini:

_instance :null
Both singleton are same

Di sini contoh Singleton yang dibuat oleh threadA dan threadB sama. Itu berarti threadB sedang menunggu di luar sampai threadA melepaskan kunci itu.

Sekarang ganti Singleton.java dengan berkomentar Thread.sleep (500); metode dan uncommenting Singleton.class.wait (500); . Di sini karena Singleton.class.wait (500); metode threadA akan melepaskan semua kunci yang diperoleh dan bergerak ke status "Non Runnable", threadB akan mendapatkan perubahan untuk masuk dalam blok yang disinkronkan.

Sekarang jalankan lagi:

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

Di sini Singleton instance yang dibuat oleh threadA dan threadB TIDAK sama karena threadB mendapat perubahan untuk masuk dalam blok yang disinkronkan dan setelah 500 milidetik threadA mulai dari posisi terakhirnya dan membuat satu lagi objek Singleton.

Dhiral Pandya
sumber
2

Harus dipanggil dari blok yang disinkronkan: wait() metode selalu dipanggil dari blok yang disinkronkan, yaitu wait()metode perlu mengunci monitor objek sebelum objek yang dipanggil. Tetapi sleep()metode dapat dipanggil dari luar blok disinkronkan yaitu sleep()metode tidak memerlukan monitor objek.

IllegalMonitorStateException: jika wait()metode dipanggil tanpa memperoleh kunci objek daripada IllegalMonitorStateExceptionyang dilempar saat runtime, tetapi sleep()metode tidak pernah melempar pengecualian seperti itu.

Milik kelas mana: wait() metode milik java.lang.Objectkelas tetapi sleep()metode milik java.lang.Threadkelas.

Disebut pada objek atau utas: wait() metode dipanggil pada objek tetapi sleep()metode dipanggil pada Utas bukan objek.

Statuswait() utas : saat metode dipanggil pada objek, utas yang memegang monitor objek beralih dari menjalankan ke status menunggu dan dapat kembali ke status dapat dijalankan hanya ketika notify()atau notifyAll()metode dipanggil pada objek tersebut. Dan kemudian penjadwal thread menjadwalkan utas untuk beralih dari dari runnable ke running state. ketika sleep()dipanggil pada utas, ia beralih dari menjalankan ke status menunggu dan dapat kembali ke status dapat dijalankan saat waktu tidur habis.

Ketika dipanggil dari blok yang disinkronkan: ketika wait()metode dipanggil thread meninggalkan kunci objek. Tetapi sleep()metode ketika dipanggil dari blok yang disinkronkan atau metode thread tidak meninggalkan kunci objek.

Untuk Referensi Lebih Lanjut

AVI
sumber
mungkin URL referensi yang lebih baik daripada yang itu.
Drew
2

Dari halaman dokumentasi oracle pada metode wait () dari Object:

public final void wait()
  1. Menyebabkan utas saat ini menunggu sampai utas lain memanggil notify()metode atau notifyAll()metode untuk objek ini. Dengan kata lain, metode ini berperilaku persis seolah-olah hanya melakukan panggilan wait(0).
  2. Utas saat ini harus memiliki monitor objek ini. Utas melepaskan kepemilikan monitor ini dan menunggu hingga utas lainnya memberi tahu utas yang menunggu monitor objek ini untuk bangun
  3. interupsi dan bangun palsu dimungkinkan
  4. Metode ini seharusnya hanya dipanggil oleh utas yang merupakan pemilik monitor objek ini

Metode ini melempar

  1. IllegalMonitorStateException - jika utas saat ini bukan pemilik monitor objek.

  2. InterruptedException- jika ada utas yang mengganggu utas saat ini sebelum atau saat utas saat ini sedang menunggu pemberitahuan. Status terputus dari utas saat ini dihapus ketika pengecualian ini dilemparkan.

Dari halaman dokumentasi oracle tentang metode sleep ()Thread :

public static void sleep(long millis)
  1. Menyebabkan thread yang saat ini mengeksekusinya tertidur (menghentikan sementara eksekusi) untuk jumlah milidetik yang ditentukan, tergantung pada ketepatan dan keakuratan timer dan penjadwal sistem.
  2. Utas tidak kehilangan kepemilikan monitor apa pun.

Metode ini melempar:

  1. IllegalArgumentException - jika nilai millis negatif

  2. InterruptedException- jika ada utas yang mengganggu utas saat ini. Status terputus dari utas saat ini dihapus ketika pengecualian ini dilemparkan.

Perbedaan utama lainnya:

wait()adalah metode non-statis (metode instance) tidak seperti metode statis sleep()(metode kelas).

Ravindra babu
sumber
1

wait()diberikan di dalam metode yang disinkronkan sedangkan sleep()diberikan di dalam metode yang tidak disinkronkan karena wait()metode melepaskan kunci pada objek tetapi sleep()atau yield()tidak melepaskan lock().

Aravind Mano
sumber
sleep()bisa di dalam synchronizedblok atau metode. Jawaban tidak menjelaskan apa pun.
Marquis of Lorne
1
  • Metode wait(1000) menyebabkan utas saat ini tidur hingga satu detik .
    • Utas dapat tidur kurang dari 1 detik jika menerima notify()ataunotifyAll() panggilan metode .
  • Panggilan ke sleep(1000) menyebabkan utas saat ini tertidur selama tepat 1 detik .
    • Juga thread tidur tidak dapat mengunci sumber daya apa pun . Tapi utas menunggu tidak.
Rupesh
sumber
1
sleep(1000)tidak menjamin untuk tidur selama tepat 1 detik. Mungkin terputus sebelumnya.
Lucio
1
Posting ini sangat membingungkan. Semua posting lain di utas ini mengatakan bahwa utas tidur TIDAK memegang kunci dan bahwa utas tunggu TIDAK memegang kunci. Demikian pula pos dengan diagram menyiratkan bahwa panggilan untuk memberi tahu () membangun utas tidur tetapi pos lainnya (dan diagram status utas) menyiratkan bahwa hanya interupsi () atau periode waktu habis yang lewat yang melakukan ini. Saya baru saja memesan sendiri salinan konkurensi java dalam praktik, sesuatu yang seharusnya sudah lama saya baca!
berimbolo
1

Sebenarnya, semua ini dengan jelas dijelaskan dalam dokumen Java (tapi saya menyadari ini hanya setelah membaca jawabannya).

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

wait () - Utas saat ini harus memiliki monitor objek ini. Utas melepaskan kepemilikan monitor ini dan menunggu hingga utas lainnya memberi tahu utas yang menunggu monitor objek ini untuk bangun melalui panggilan ke metode notify atau metode notifyAll. Utas kemudian menunggu hingga mendapatkan kembali kepemilikan monitor dan melanjutkan eksekusi.

sleep () - Menyebabkan thread yang saat ini mengeksekusinya tertidur (menghentikan sementara eksekusi) untuk jumlah milidetik yang ditentukan, tergantung pada ketepatan dan keakuratan pengatur waktu dan penjadwal sistem. Utas tidak kehilangan kepemilikan monitor apa pun.

TT_
sumber