Der

„Hallo, Amigo!“

„Ich möchte mit Ihnen ausführlich auf Wait-Notify eingehen. Die Wait-Notify-Methoden bieten einen praktischen Mechanismus für die Interaktion von Threads. Sie können auch zum Aufbau komplexer High-Level-Mechanismen für die Thread-Interaktion verwendet werden.“

„Ich beginne mit einem kleinen Beispiel. Angenommen, wir haben ein Programm für einen Server, das verschiedene Aufgaben ausführen muss, die von Benutzern über eine Website erstellt wurden. Benutzer können verschiedene Aufgaben zu unterschiedlichen Zeiten hinzufügen. Die Aufgaben sind ressourcenintensiv, aber die unseres Servers 8 -Core-Prozessor zurechtkommt. Wie sollen wir die Aufgaben auf dem Server ausführen?“

„Zuerst erstellen wir eine Gruppe von Arbeitsthreads, so viele wie Prozessorkerne vorhanden sind. Jeder Thread kann auf seinem eigenen Kern laufen: Die Threads stören sich nicht gegenseitig und die Prozessorkerne auch nicht.“ Im Leerlauf sitzen."

„Zweitens erstellen wir ein Warteschlangenobjekt, dem die Aufgaben der Benutzer hinzugefügt werden. Verschiedene Arten von Aufgaben entsprechen unterschiedlichen Objekten, aber alle implementieren die Runnable-Schnittstelle, damit sie ausgeführt werden können.“

„Könnten Sie mir ein Beispiel für ein Aufgabenobjekt geben?“

"Hör zu:"

Eine Klasse, die n Fakultäten berechnet, wenn die run()-Methode aufgerufen wird
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;
 }
}

"So weit, ist es gut."

„Großartig. Dann schauen wir uns an, wie ein Warteschlangenobjekt aussehen sollte. Was können Sie mir darüber sagen?“

„Es muss Thread-sicher sein. Es wird von einem Thread mit Aufgabenobjekten geladen, die diese von Benutzern erhalten, und dann werden die Aufgaben von Arbeitsthreads übernommen.“

„Ja. Und was ist, wenn uns eine Zeit lang die Aufgaben ausgehen?“

„Dann sollten die Worker-Threads warten, bis es mehr gibt.“

„Das ist richtig. Stellen Sie sich nun vor, dass dies alles in einer einzigen Warteschlange erstellt werden kann. Schauen Sie es sich an:“

Eine Aufgabenwarteschlange. Wenn keine Aufgaben vorhanden sind, schläft der Thread ein und wartet auf das Erscheinen einer Aufgabe:
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);
 }
}

„Wir haben eine getJob- Methode, die prüft, ob die Aufgabenliste leer ist. Der Thread geht dann in den Ruhezustand (wartet), bis etwas in der Liste erscheint.“

„Es gibt auch die Put- Methode, mit der Sie der Liste eine neue Aufgabe hinzufügen können. Sobald eine neue Aufgabe hinzugefügt wird, wird die notifyAll- Methode aufgerufen. Der Aufruf dieser Methode weckt alle Worker-Threads, die innerhalb der getJob-Methode eingeschlafen sind.“

„Können Sie sich noch einmal daran erinnern, wie die Warte- und Benachrichtigungsmethoden funktionieren?“

„Die Wait-Methode wird nur innerhalb eines synchronisierten Blocks auf einem Mutex-Objekt aufgerufen. In unserem Fall: dies. Darüber hinaus passieren zwei Dinge:

1) Der Thread schläft ein.

2) Der Thread gibt den Mutex vorübergehend frei (bis er aufwacht).

„Danach können andere Threads in den synchronisierten Block eintreten und denselben Mutex erwerben.“

„Die notifyAll- Methode kann auch nur innerhalb des synchronisierten Blocks eines Mutex-Objekts aufgerufen werden. In unserem Fall: dies. Außerdem passieren zwei Dinge:“

1) Alle Threads, die auf dieses Mutex-Objekt warten, werden aktiviert.

2) Sobald der aktuelle Thread den synchronisierten Block verlässt, übernimmt einer der aktivierten Threads den Mutex und setzt seine Arbeit fort. Wenn der Mutex freigegeben wird, erhält ein anderer aktivierter Thread den Mutex usw.

„Es ist einem Bus sehr ähnlich. Man steigt ein und möchte den Fahrpreis bezahlen, aber es gibt keinen Fahrer. Also „schläft man ein“. Irgendwann ist der Bus voll, aber es gibt immer noch niemanden, dem man den Fahrpreis geben kann. Dann der Fahrer kommt und sagt: „Kosten, bitte.“ Und das ist der Anfang von…“

„Interessanter Vergleich. Aber was ist ein Bus?“

„Julio hat das erklärt. Es gab diese seltsamen Dinge, die im 21. Jahrhundert verwendet wurden.“