Als ich über Latches und Cyclicbarriers studierte, kam ich auf diese Metaphern.
Cyclicbarriers : Stellen Sie sich vor, ein Unternehmen hat einen Besprechungsraum. Um das Meeting zu starten, muss eine bestimmte Anzahl von Meeting-Teilnehmern zum Meeting kommen (um es offiziell zu machen). Das Folgende ist der Code eines normalen Besprechungsteilnehmers (eines Mitarbeiters).
class MeetingAtendee implements Runnable {
CyclicBarrier myMeetingQuorumBarrier;
public MeetingAtendee(CyclicBarrier myMileStoneBarrier) {
this.myMeetingQuorumBarrier = myMileStoneBarrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " i joined the meeting ...");
myMeetingQuorumBarrier.await();
System.out.println(Thread.currentThread().getName()+" finally meeting stared ...");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
System.out.println("Meeting canceled! every body dance <by chic band!>");
}
}
}
Der Mitarbeiter nimmt an der Besprechung teil und wartet darauf, dass andere Personen zur Besprechung kommen. Außerdem wird er verlassen, wenn das Meeting abgesagt wird :) Dann haben wir THE BOSS, wie Dosen nicht gerne darauf warten, dass andere auftauchen, und wenn er seinen Patienten verliert, bricht er das Meeting ab.
class MeetingAtendeeTheBoss implements Runnable {
CyclicBarrier myMeetingQuorumBarrier;
public MeetingAtendeeTheBoss(CyclicBarrier myMileStoneBarrier) {
this.myMeetingQuorumBarrier = myMileStoneBarrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "I am THE BOSS - i joined the meeting ...");
//boss dose not like to wait too much!! he/she waits for 2 seconds and we END the meeting
myMeetingQuorumBarrier.await(1,TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName()+" finally meeting stared ...");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
System.out.println("what WHO canceled The meeting");
} catch (TimeoutException e) {
System.out.println("These employees waste my time!!");
}
}
}
An einem normalen Tag kommen Mitarbeiter zu Besprechungen und warten darauf, dass andere auftauchen. Wenn einige Teilnehmer nicht kommen, müssen sie auf unbestimmte Zeit warten! In einer besonderen Besprechung kommt der Chef und er wartet nicht gern. (5 Personen müssen mit der Besprechung beginnen, aber nur der Chef und auch ein begeisterter Mitarbeiter.) Er bricht die Besprechung ab (wütend).
CyclicBarrier meetingAtendeeQuorum = new CyclicBarrier(5);
Thread atendeeThread = new Thread(new MeetingAtendee(meetingAtendeeQuorum));
Thread atendeeThreadBoss = new Thread(new MeetingAtendeeTheBoss(meetingAtendeeQuorum));
atendeeThread.start();
atendeeThreadBoss.start();
Ausgabe:
//Thread-1I am THE BOSS - i joined the meeting ...
// Thread-0 i joined the meeting ...
// These employees waste my time!!
// Meeting canceled! every body dance <by chic band!>
Es gibt ein anderes Szenario, in dem ein anderer externer Thread (ein Erdbeben) das Meeting abbricht (Call-Reset-Methode). In diesem Fall werden alle wartenden Threads durch eine Ausnahme geweckt.
class NaturalDisasters implements Runnable {
CyclicBarrier someStupidMeetingAtendeeQuorum;
public NaturalDisasters(CyclicBarrier someStupidMeetingAtendeeQuorum) {
this.someStupidMeetingAtendeeQuorum = someStupidMeetingAtendeeQuorum;
}
void earthQuakeHappening(){
System.out.println("earth quaking.....");
someStupidMeetingAtendeeQuorum.reset();
}
@Override
public void run() {
earthQuakeHappening();
}
}
Das Ausführen von Code führt zu einer lustigen Ausgabe:
// Thread-1I am THE BOSS - i joined the meeting ...
// Thread-0 i joined the meeting ...
// earth quaking.....
// what WHO canceled The meeting
// Meeting canceled! every body dance <by chic band!>
Sie können dem Besprechungsraum auch eine Sekretärin hinzufügen. Wenn eine Besprechung stattfindet, dokumentiert sie alles, ist jedoch nicht Teil der Besprechung:
class MeetingSecretary implements Runnable {
@Override
public void run() {
System.out.println("preparing meeting documents");
System.out.println("taking notes ...");
}
}
Latches : Wenn der verärgerte Chef eine Ausstellung für Firmenkunden veranstalten möchte, muss alles bereit sein (Ressourcen). Wir stellen eine To-Do-Liste zur Verfügung, in der jeder Arbeiter (Thread) seine Arbeit erledigt, und wir überprüfen die To-Do-Liste (einige Arbeiter malen, andere bereiten das Soundsystem vor ...). Wenn alle Aufgaben in der Aufgabenliste vollständig sind (Ressourcen werden bereitgestellt), können wir den Kunden die Türen öffnen.
public class Visitor implements Runnable{
CountDownLatch exhibitonDoorlatch = null;
public Visitor (CountDownLatch latch) {
exhibitonDoorlatch = latch;
}
public void run() {
try {
exhibitonDoorlatch .await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("customer visiting exebition");
}
}
Und die Arbeiter, wie bereiten sie die Ausstellung vor:
class Worker implements Runnable {
CountDownLatch myTodoItem = null;
public Worker(CountDownLatch latch) {
this.myTodoItem = latch;
}
public void run() {
System.out.println("doing my part of job ...");
System.out.println("My work is done! remove it from todo list");
myTodoItem.countDown();
}
}
CountDownLatch preperationTodoList = new CountDownLatch(3);
// exhibition preparation workers
Worker electricalWorker = new Worker(preperationTodoList);
Worker paintingWorker = new Worker(preperationTodoList);
// Exhibition Visitors
ExhibitionVisitor exhibitionVisitorA = new ExhibitionVisitor(preperationTodoList);
ExhibitionVisitor exhibitionVisitorB = new ExhibitionVisitor(preperationTodoList);
ExhibitionVisitor exhibitionVisitorC = new ExhibitionVisitor(preperationTodoList);
new Thread(electricalWorker).start();
new Thread(paintingWorker).start();
new Thread(exhibitionVisitorA).start();
new Thread(exhibitionVisitorB).start();
new Thread(exhibitionVisitorC).start();