4

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?

grg-n-sox
  • 717
  • 2
  • 5
  • 25
  • 2
    What does worker.meetingWait() do? – Christopher Schultz Apr 18 '12 at 16:42
  • I have a teammate that is primarily responsible for the Employee class and mentioned he wanted to have the state of the Employee updated throughout the meeting, including if the Employee is actually attending an active meeting or just waiting. That's what the meetingWait() and meetingStart() methods are for. – grg-n-sox Apr 18 '12 at 18:21

1 Answers1

4

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
     }
 }
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • 1
    +1 [`CyclicBarrier`](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html) is definitely a better fit. [`CountDownLatch`](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html) usually implies separate waiting vs. counting-down threads. – David Harkness Apr 18 '12 at 18:02
  • I probably should have mentioned this in the question then. The constructor for the meeting takes a list of employees that are to attend. When a room becomes available, the room takes the meeting and calls the startMeeting() method on the meeting object, which in turn calls a meetingRequest() method on all the Employee objects in the list. @DavidHarkness The reason a CountDownLatch is used is because a new meeting object is used for each meeting. Since the meeting object more or less encapsulates a single event, it seemed to be more fitting to use a CountDownLatch than a CyclicBarrier. – grg-n-sox Apr 18 '12 at 18:24
  • @grg-n-sox Ok, do you see why your program will only have a single Employee arrive though? What you need to have is the Employee thread calling the method which has the latch `await()`ing. The Employee thread will then be suspended, not the main thread that is starting the meeting. So this main thread that is starting the meeting should notify the threads to wait for the meeting to begin, what you have is the thread starting is waiting for all the other threads to wait on the meeting, obviously it has to be the other way around. – John Vint Apr 18 '12 at 18:28
  • I guess I see what you mean, but you keep referring to a main thread that is starting the meeting. However, in this case, it is the employees themselves that determine when a meeting needs to occur and whoever does initialize the meeting attempts to add it to the room where if it is empty, it immediately starts and if it is full, the meeting gets added to a BlockingQueue. – grg-n-sox Apr 18 '12 at 18:33
  • I guess when I refer to the main thread I mean the thread that is starting the meeting. The first time that thread tries to await on an employee it is actually suspending it's own thread and no further progress can be made. So as I mention you would rather notify the other employees attend/wait for the meeting to start. – John Vint Apr 18 '12 at 18:35