Quando studiavo chiusure e barriere cicliche, mi sono inventato queste metafore.
barriere cicliche : immagina che un'azienda abbia una sala riunioni. Per iniziare la riunione, un certo numero di partecipanti alla riunione deve venire alla riunione (per renderla ufficiale). il seguente è il codice di un normale partecipante alla riunione (un dipendente)
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!>");
}
}
}
l'impiegato si unisce alla riunione, attende che gli altri vengano per iniziare la riunione. inoltre viene abbandonato se la riunione viene annullata :) quindi abbiamo THE BOSS come le dosi non amano aspettare che gli altri si presentino e se perde il suo paziente, annulla la riunione.
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!!");
}
}
}
In una giornata normale, i dipendenti vengono alla riunione in attesa che altri si presentino e se alcuni partecipanti non arrivano devono aspettare indefinitamente! in una riunione speciale il capo arriva e non gli piace aspettare (5 persone devono iniziare la riunione, ma arriva solo il capo e anche un dipendente entusiasta), quindi annulla la riunione (con rabbia)
CyclicBarrier meetingAtendeeQuorum = new CyclicBarrier(5);
Thread atendeeThread = new Thread(new MeetingAtendee(meetingAtendeeQuorum));
Thread atendeeThreadBoss = new Thread(new MeetingAtendeeTheBoss(meetingAtendeeQuorum));
atendeeThread.start();
atendeeThreadBoss.start();
Produzione:
//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!>
Esiste un altro scenario in cui un altro thread esterno (un terremoto) annulla la riunione (metodo di reimpostazione della chiamata). in questo caso tutti i thread in attesa vengono svegliati da un'eccezione.
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();
}
}
l'esecuzione del codice produrrà un output divertente:
// 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!>
Puoi anche aggiungere un segretario alla sala riunioni, se si tiene una riunione documenterà ogni cosa ma non fa parte della riunione:
class MeetingSecretary implements Runnable {
@Override
public void run() {
System.out.println("preparing meeting documents");
System.out.println("taking notes ...");
}
}
Chiusure : se il capo arrabbiato vuole organizzare un'esibizione per i clienti dell'azienda, ogni cosa deve essere pronta (risorse). forniamo un elenco di cose da fare per ogni lavoratore (Discussione) che dosa il suo lavoro e controlliamo l'elenco di cose da fare (alcuni lavoratori dipingono, altri preparano il sistema audio ...). quando tutti gli elementi nella lista delle cose da fare sono completi (vengono fornite le risorse) possiamo aprire le porte ai clienti.
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");
}
}
E i lavoratori come stanno preparando la mostra:
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();