multithreading - Java CountDownLatch with Threads -
i looking learn using java countdownlatch control execution of thread.
i have 2 classes. 1 called poller
, other referendum
. threads created in referendum
class , run()
methods contained in poller
class.
in poller , referendum classes have imported java countdown latch via import java.util.concurrent.countdownlatch
.
i looking understand why , the *.countdown();
, *.await();
statements need applied , understand if have correctly initialised countdownlatch within poller
constructor.
the complete code 2 classes are:
import java.util.concurrent.countdownlatch; public class poller extends thread { private string id; // pollster id private int pollsize; // number of samples private int numberofpolls; // number of times perform poll private referendum referendum; // referendum (implies voting population) private int sampledvotes[]; // counts of votes or against static countdownlatch pollsarecomplete; //the countdownlatch /** * constructor polling organisation. * @param r referendum on poller gathering stats * @param id name of polling organisation * @param pollsize size of poll poller use * @param polltimes number of times poller conduct poll * @param alatch coutn down latch prevents referendum results being published */ public poller(referendum r, string id, int pollsize, int polltimes, countdownlatch alatch) { this.referendum = r; this.id = id; this.pollsize = pollsize; this.numberofpolls = polltimes; this.pollsarecomplete = alatch; alatch = new countdownlatch(3); // , against votes counted sampledvotes = new int[2]; } // getter numberofpolls public int getnumberofpolls() { return numberofpolls; } @override //to use countdown latch public void run() { (int = 0; < getnumberofpolls(); i++) { resetvotes(); pollvotes(); publishpollresults(); } } // make sure sampledvotes reset 0 protected void resetvotes() { // initialise vote counts in poll (int = 0; < sampledvotes.length; i++) { sampledvotes[i] = 0; } } // sampling way citizens vote in referendum protected void pollvotes() { (int n = 0; n < pollsize; n++) { citizen c = referendum.pickrandomcitizen(); //as things stand, pickrandomcitizen can return null //because haven't protected access collection if (c != null) { sampledvotes[c.votefor()]++; } } } protected void publishpollresults() { int vfor = 100 * sampledvotes[referendum.for] / pollsize; int vagainst = 100 * sampledvotes[referendum.against] / pollsize; system.out.printf("according %-20s \t(", this.id + ":"); system.out.print("for " + vfor); try { thread.sleep(1000); } catch (exception e) { e.printstacktrace(); } system.out.println(", against " + vagainst + ")"); } }
and
import java.util.linkedlist; import java.util.list; import java.util.concurrent.countdownlatch; public class referendum { private list<citizen> citizens; //voters private list<poller> pollers; //vote samplers public static final int = 0; //index votes array public static final int against = 1; //index votes array private int votes[]; //for , against votes counters public referendum(int population) { citizens = new linkedlist<citizen>(); pollers = new linkedlist<poller>(); // initialise referendum population (int = 0; < population; i++) { citizen c = new citizen(i % 4); //suppose equal party membership citizens.add(c); } votes = new int[2]; //in example, or against } public void addpoller(poller np) { pollers.add(np); } public citizen removecitizen(int i) { return citizens.remove(i); } public list<poller> getpollers() { return pollers; } public void startpollswithlatch() { //create poller threads use latch addpoller(new poller(this, "the daily day", 100, 3, poller.pollsarecomplete)); addpoller(new poller(this, "stats people", 100, 3, poller.pollsarecomplete)); addpoller(new poller(this, "tv pundits", 100, 3, poller.pollsarecomplete)); // start polls (poller p : pollers) { p.start(); } } // pick citizen randomly - access not controlled yet public citizen pickrandomcitizen() { //todo add code method part (b) citizen randomcitizen; // first random index int index = (int) (math.random() * getpopulationsize()); randomcitizen = citizens.remove(index); return randomcitizen; } // counting actual votes cast in referendum public void castvotes() { (int h = 0; h < getpopulationsize(); h++) { citizen c = citizens.get(h); votes[c.votefor()]++; } } // tell size of population public int getpopulationsize() { return citizens.size(); } // display referendum results public void revealresults() { system.out.println(" **** referendum results out! ****"); system.out.println("for"); system.out.printf("\t %.2f %%\n", 100.0 * votes[for] / getpopulationsize()); system.out.println("against"); system.out.printf("\t %.2f %%\n", 100.0 * votes[against] / getpopulationsize()); } public static void main(string[] args) { // initialise referendum. number of people // has been made smaller here reduce simulation time. referendum r = new referendum(50000); r.startpollswithlatch(); r.castvotes(); // reveal results of referendum r.revealresults(); } }
in nutshell... threads must execute publishpollresults();
statement before revealresults();
executed.
ok,
now, if publishpollresults must done before reavelresults, need wait proper count in reaveal method. so, latch must shared referendum object not pollers.
so, let referendum creates latch , pass pollers:
public class referendum { countdownlatch pollsarecomplete; ... public void startpollswithlatch() { pollsarecomplete = new countdownlatch(3); //create new latch know when voting done //create poller threads use latch addpoller(new poller(this, "the daily day", 100, 3, pollsarecomplete)); //pass pollers addpoller(new poller(this, "stats people", 100, 3, pollsarecomplete)); addpoller(new poller(this, "tv pundits", 100, 3, pollsarecomplete)); // start polls (poller p : pollers) { p.start(); } } public void revealresults() { pollsarecomplete.await(); //we can pass line if latch count went 0 system.out.println(" **** referendum results out! ****"); .... } }
so pollers should share latch. using static variable okish want able use pollers different referendums. betther, have instance field , pass in constructor (you kind of started constructor passed value static variable makes no sense (and actaully null).
public class poller extends thread { ... private countdownlatch pollsarecomplete; //the countdownlatch shared referendum public poller(referendum r, string id, int pollsize, int polltimes, countdownlatch alatch) { ... this.pollsarecomplete = alatch; } public void run() { (int = 0; < getnumberofpolls(); i++) { resetvotes(); pollvotes(); publishpollresults(); } pollsarecomplete.countdown(); //voting finished, let referendum publish results. } }
so once poller finished work lowers latch, , when referendum can continue , print results.
mind poller thread publish results 3 times (as have loop) , when 3 cycles down signal referendum.
if wanted 3 separate phases of referendum difficult achieve if latch cannot reset once it's been down 0.