Itu

"Hai, Amigo!"

"Saya ingin menyelam lebih dalam dengan Anda tentang tunggu-beri tahu. Metode tunggu-beri tahu menyediakan mekanisme yang nyaman bagi utas untuk berinteraksi. Mereka juga dapat digunakan untuk membangun mekanisme tingkat tinggi yang kompleks untuk interaksi utas."

"Saya akan mulai dengan contoh kecil. Misalkan kita memiliki program untuk server yang harus melakukan berbagai tugas yang dibuat oleh pengguna melalui situs web. Pengguna dapat menambahkan berbagai tugas pada waktu yang berbeda. Tugas tersebut membutuhkan banyak sumber daya, tetapi server kami 8 prosesor -core bisa mengatasinya. Bagaimana seharusnya kita melakukan tugas di server?"

"Pertama, kita akan membuat grup utas pekerja, sebanyak inti prosesor. Setiap utas akan dapat berjalan pada intinya sendiri: Utas tidak akan saling mengganggu, dan inti prosesor tidak akan duduk diam."

"Kedua, kita akan membuat objek antrean tempat tugas pengguna akan ditambahkan. Jenis tugas yang berbeda akan sesuai dengan objek yang berbeda, tetapi semuanya akan mengimplementasikan antarmuka Runnable sehingga dapat dijalankan."

"Bisakah Anda memberi saya contoh objek tugas?"

"Coba lihat:"

Kelas yang menghitung n faktorial saat metode run() dipanggil
class Factorial implements Runnable
{
 public int n = 0;
 public long result = 1;

 public Factorial (int n)
 {
  this.n = n;
 }

 public void run()
 {
  for (int i = 2; i <= n; i++)
   result *= i;
 }
}

"Sejauh ini bagus."

"Bagus. Kalau begitu mari kita periksa bagaimana tampilan objek antrean. Apa yang bisa Anda ceritakan tentangnya?"

"Itu harus aman untuk thread. Itu dimuat dengan objek tugas oleh utas yang menerimanya dari pengguna, dan kemudian tugas diambil oleh utas pekerja."

"Ya. Dan bagaimana jika kita kehabisan tugas untuk sementara waktu?"

"Maka utas pekerja harus menunggu sampai ada lebih banyak."

"Betul. Sekarang bayangkan semua ini dapat dibangun dalam satu antrean. Coba lihat:"

Antrean tugas. Jika tidak ada tugas, maka utas akan tertidur dan menunggu tugas muncul:
public class JobQueue
{
 ArrayList jobs = new ArrayList();

 public synchronized void put(Runnable job)
 {
  jobs.add(job);
  this.notifyAll();
 }

 public synchronized Runnable getJob()
 {
  while (jobs.size() == 0)
   this.wait();

  return jobs.remove(0);
 }
}

"Kami memiliki metode getJob yang memeriksa apakah daftar tugas kosong. Utas kemudian tertidur (menunggu) hingga sesuatu muncul dalam daftar."

"Ada juga metode put , yang memungkinkan Anda menambahkan tugas baru ke dalam daftar. Segera setelah tugas baru ditambahkan, metode notifyAll dipanggil. Memanggil metode ini akan membangkitkan semua thread pekerja yang tertidur di dalam metode getJob."

"Dapatkah Anda mengingat kembali cara kerja metode tunggu dan beri tahu?"

"Metode tunggu hanya dipanggil di dalam blok tersinkronisasi, pada objek mutex. Dalam kasus kami: ini. Selain itu, dua hal terjadi:

1) Utas tertidur.

2) Utas untuk sementara melepaskan mutex (sampai bangun).

"Setelah itu, utas lain dapat memasuki blok yang disinkronkan dan memperoleh mutex yang sama."

" Metode notifyAll juga hanya dapat dipanggil di dalam blok tersinkronisasi dari objek mutex. Dalam kasus kami: ini. Selain itu, dua hal terjadi:"

1) Semua utas yang menunggu objek mutex ini dibangunkan.

2) Setelah utas saat ini keluar dari blok yang disinkronkan, salah satu utas yang terbangun memperoleh mutex dan melanjutkan pekerjaannya. Saat melepaskan mutex, utas lain yang terbangun memperoleh mutex, dll.

"Ini sangat mirip dengan bus. Anda masuk dan ingin membayar ongkos Anda, tetapi tidak ada pengemudi. Jadi Anda «tertidur». Akhirnya, bus sudah penuh, tetapi masih belum ada yang memberi ongkos. Lalu pengemudi datang dan berkata, «Harga, tolong». Dan ini adalah awal dari..."

"Perbandingan yang menarik. Tapi apa itu bus?"

"Julio menjelaskan ini. Ada hal-hal aneh yang digunakan di abad ke-21."