Det

"Hej, Amigo!"

"Jeg vil gerne dykke dybt med dig angående vent-besked. Vent-besked metoderne giver en bekvem mekanisme for tråde til at interagere. De kan også bruges til at bygge komplekse højniveaumekanismer til trådinteraktion."

"Jeg starter med et lille eksempel. Antag, at vi har et program til en server, der skal udføre forskellige opgaver, der er oprettet af brugere gennem en hjemmeside. Brugere kan tilføje forskellige opgaver på forskellige tidspunkter. Opgaverne er ressourcekrævende, men vores servers 8 -core processor kan klare. Hvordan skal vi udføre opgaverne på serveren?"

"Først vil vi oprette en gruppe arbejdstråde, lige så mange som der er processorkerner. Hver tråd vil kunne køre på sin egen kerne: Trådene vil ikke forstyrre hinanden, og processorkernerne vil ikke sidde ledig."

"For det andet opretter vi et køobjekt, hvor brugernes opgaver vil blive tilføjet. Forskellige typer opgaver vil svare til forskellige objekter, men alle vil implementere Runnable-grænsefladen, så de kan køres."

"Kan du give mig et eksempel på et opgaveobjekt?"

"Tjek det ud:"

En klasse, der beregner n factorial, når run() metoden kaldes
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;
 }
}

"Så langt så godt."

"Fint. Lad os så undersøge, hvordan et køobjekt skal se ud. Hvad kan du fortælle mig om det?"

"Det skal være trådsikkert. Det indlæses med opgaveobjekter af en tråd, der modtager dem fra brugere, og så samles opgaverne op af arbejdertråde."

"Jep. Og hvad hvis vi løber tør for opgaver for en tid?"

"Så burde arbejdertrådene vente, til der er flere."

"Det er rigtigt. Forestil dig nu, at alt dette kan bygges i en enkelt kø. Tjek det ud:"

En opgavekø. Hvis der ikke er nogen opgaver, falder tråden i søvn og venter på, at en dukker op:
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);
 }
}

"Vi har en getJob- metode, der tjekker om opgavelisten er tom. Tråden går så i dvale (venter), indtil der dukker noget op på listen."

"Der er også put- metoden, som lader dig tilføje en ny opgave til listen. Så snart en ny opgave tilføjes, kaldes notifyAll- metoden. Ved at kalde denne metode vækkes alle arbejdertråde, der faldt i søvn i getJob-metoden."

"Kan du huske igen, hvordan vente- og underretningsmetoderne fungerer?"

"Ventmetoden kaldes kun inde i en synkroniseret blok, på et mutex-objekt. I vores tilfælde: dette. Desuden sker der to ting:

1) Tråden falder i søvn.

2) Tråden frigiver midlertidigt mutexen (indtil den vågner).

"Derefter kan andre tråde komme ind i den synkroniserede blok og erhverve den samme mutex."

" NotifyAll- metoden kan også kun kaldes inde i den synkroniserede blok af et mutex-objekt. I vores tilfælde: dette. Desuden sker der to ting:"

1) Alle tråde, der venter på dette mutex-objekt, vækkes.

2) Når den aktuelle tråd forlader den synkroniserede blok, erhverver en af ​​de vækkede tråde mutex'en og fortsætter sit arbejde. Når den frigiver mutex'en, erhverver en anden vækket tråd mutex'en osv.

"Det minder meget om en bus. Du går ind og vil betale din billet, men der er ingen chauffør. Så du "falder i søvn". Til sidst er bussen pakket, men der er stadig ingen at give billetten til. Så chaufføren ankommer og siger: "Fare, please". Og dette er begyndelsen på..."

"Interessant sammenligning. Men hvad er en bus?"

"Julio forklarede dette. Der blev brugt disse mærkelige ting i det 21. århundrede."