The

"Hai, Amigo!"

"Saya ingin menyelam lebih mendalam dengan anda tentang tunggu-maklum. Kaedah tunggu-maklumkan menyediakan mekanisme yang mudah untuk benang berinteraksi. Ia juga boleh digunakan untuk membina mekanisme peringkat tinggi yang kompleks untuk interaksi benang."

"Saya akan mulakan dengan contoh kecil. Katakan kita mempunyai program untuk pelayan yang mesti melaksanakan pelbagai tugas yang dibuat oleh pengguna melalui tapak web. Pengguna boleh menambah pelbagai tugas pada masa yang berbeza. Tugasan adalah intensif sumber, tetapi pelayan kami 8 -pemproses teras boleh mengatasi. Bagaimanakah kita harus melaksanakan tugas pada pelayan?"

"Pertama, kami akan mencipta sekumpulan benang pekerja, seberapa banyak yang terdapat teras pemproses. Setiap utas akan dapat berjalan pada terasnya sendiri: Benang tidak akan mengganggu satu sama lain, dan teras pemproses tidak akan duduk terbiar."

"Kedua, kami akan mencipta objek baris gilir di mana tugas pengguna akan ditambah. Jenis tugas yang berbeza akan sepadan dengan objek yang berbeza, tetapi kesemuanya akan melaksanakan antara muka Runnable supaya ia boleh dijalankan."

"Bolehkah anda memberi saya contoh objek tugasan?"

"Lihatlah:"

Kelas yang mengira n faktorial apabila kaedah 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;
 }
}

"Setakat ini, begitu baik."

"Hebat. Kalau begitu mari kita periksa bagaimana rupa objek baris gilir. Apa yang boleh anda beritahu saya mengenainya?"

"Ia mestilah selamat untuk benang. Ia dimuatkan dengan objek tugasan oleh benang yang menerimanya daripada pengguna, dan kemudian tugasan diambil oleh benang pekerja."

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

"Kemudian benang pekerja harus menunggu sehingga ada lagi."

"Betul. Sekarang bayangkan bahawa semua ini boleh dibina dalam satu baris gilir. Lihatlah:"

Barisan tugasan. Jika tiada tugas, maka benang tertidur dan menunggu satu untuk 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 mempunyai kaedah getJob yang menyemak sama ada senarai tugasan kosong. Benang kemudian tidur (menunggu) sehingga sesuatu muncul dalam senarai."

"Terdapat juga kaedah put , yang membolehkan anda menambah tugasan baharu pada senarai. Sebaik sahaja tugasan baharu ditambahkan, kaedah notifyAll dipanggil. Memanggil kaedah ini membangkitkan semua rangkaian pekerja yang tertidur di dalam kaedah getJob."

"Bolehkah anda ingat lagi bagaimana kaedah tunggu dan pemberitahuan berfungsi?"

"Kaedah tunggu hanya dipanggil di dalam blok yang disegerakkan, pada objek mutex. Dalam kes kami: ini. Selain itu, dua perkara berlaku:

1) Benang tertidur.

2) Benang melepaskan mutex buat sementara waktu (sehingga ia bangun).

"Selepas itu, utas lain boleh memasuki blok yang disegerakkan dan memperoleh mutex yang sama."

" Kaedah notifyAll juga hanya boleh dipanggil di dalam blok disegerakkan objek mutex. Dalam kes kami: ini. Selain itu, dua perkara berlaku:"

1) Semua benang yang menunggu pada objek mutex ini dikejutkan.

2) Sebaik sahaja benang semasa keluar dari blok yang disegerakkan, salah satu benang yang dibangkitkan memperoleh mutex dan meneruskan kerjanya. Apabila ia melepaskan mutex, benang lain yang terjaga memperoleh mutex, dsb.

"Ia sangat serupa dengan bas. Anda masuk dan ingin membayar tambang anda, tetapi tiada pemandu. Jadi anda «tertidur". Akhirnya, bas itu penuh sesak, tetapi masih tiada sesiapa untuk memberi tambang. Kemudian pemandu itu. tiba dan berkata, «Tolong tambang». Dan ini adalah permulaan…"

"Perbandingan yang menarik. Tetapi bas apa?"

"Julio menjelaskan perkara ini. Terdapat perkara aneh ini digunakan pada abad ke-21."