Search code examples
javaconcurrencycountdownlatch

Can Java's CountDownLatch be used from a passive class rather than a thread?


So I am working on this program that simulates a day at work and each worker is its own thread. I'm trying to implement meetings where the workers attend meetings but the meetings do not start until everyone that is supposed to be at the meeting has arrived. So I have this method for attending the meeting.

public void attendMeeting(Employee worker){
    this.cdStart.countDown();
    worker.meetingWait();
    try {
        this.cdStart.await();
        worker.meetingStart(this.length);
        if(this.attendees.get(0).equals(worker)){
            this.room.exit();
        } // end if

    } // end try
    catch (InterruptedException err) {
        // Do Nothing

    } // end catch

} // end method attendMeeting

The worker parameter being an instance of the Employee class that extends Thread and this.cdStart is the CountDownLatch. However, when running this with a meeting of four employees, only one employee seems to be able to get in, decrement the count, and hit the await() call. None of the other worker threads seem to be able to enter it. I did notice that a lot of the online examples of use pass the CountDownLock object to the threads themselves to handle. Is there a reason why this would not work instead?


Solution

  • I am assuming you are having a single thread pass in an Employee Thread object. That single thread will be waiting indefinitely until the N number of parties arrive (you need an individual thread for each Employee instance aside from the Employee thread). This means that if only one thread is continuously passing the Employee/Thread you will never get more then one Employee waiting at the meeting.

    This thread should instead, at best, signal the Employee threads to attend the Meeting.

    You should have the latch in the Meeting class and have them await on that latch. This also requires a slight restructure of the way it works.

    You pass the Meeting instance into the Employee to have that thread wait.

        public Employee extends Thread{
    
         //define this at some point whether in constructor or a 
         //means of notifying the thread to attend the meeting
          private Meeting meeting;
    
          public void run(){
              //do some stuff until this employee is ready to go  to a meeting
    
             meeting.waitForAllOthersToArrive();
          }
    
        }
    
       public class Meeting{  
         CountDownLatch latch =  new CountDownLatch(numberOfEmployees);
    
         public void waitForAllOthersToArrive(){
            latch.countDown();
            latch.await();
         } 
       }  
    

    What I would suggest for this however is a CylicBarrier. Though you wouldn't be re using it, the way the CyclicBarrier works fits better what you're trying to do, the Meeting class would then look like

     public class Meeting{
         CylicBarrier barrier = new CylicBarrier(numberOfEmployees);
    
         public void waitForAllOthersToArrive(){
             barrier.await(); //when await() is called numberOfEmployees then all waiting threads will awake
         }
     }