【问题标题】:Can Java's CountDownLatch be used from a passive class rather than a thread?Java 的 CountDownLatch 可以从被动类而不是线程中使用吗?
【发布时间】:2012-04-18 16:14:28
【问题描述】:

所以我正在开发这个模拟一天工作的程序,每个工人都是自己的线程。我正在尝试实施工人参加会议的会议,但会议直到应该参加会议的每个人都到达时才开始。所以我有这种参加会议的方法。

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

worker 参数是扩展 Thread 的 Employee 类的实例,this.cdStart 是 CountDownLatch。然而,在四名员工的会议上运行此程序时,似乎只有一名员工能够进入,减少计数,然后点击 await() 调用。其他工作线程似乎都无法进入它。我确实注意到很多在线使用示例将 CountDownLock 对象传递给线程本身来处理。有什么理由不这样做吗?

【问题讨论】:

  • worker.meetingWait() 是做什么的?
  • 我有一个主要负责 Employee 类的队友,他提到他希望在整个会议期间更新 Employee 的状态,包括 Employee 是实际参加活动会议还是只是在等待。这就是 meetingWait() 和 meetingStart() 方法的用途。

标签: java concurrency countdownlatch


【解决方案1】:

我假设您在 Employee Thread 对象中传递了一个线程。该单个线程将无限期地等待,直到 N 方到达(除了 Employee 线程之外,每个 Employee 实例都需要一个单独的线程)。这意味着如果只有一个线程不断地通过员工/线程,您将永远不会有超过一个员工在会议上等待。

此线程最多应该向员工线程发出信号以参加会议。

您应该在 Meeting 类中拥有闩锁,并让他们在该闩锁上等待。这也需要对其工作方式进行轻微调整。

您将 Meeting 实例传递给 Employee 以让该线程等待。

    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();
     } 
   }  

不过,我建议使用 CylicBarrier。虽然您不会重新使用它,但 CyclicBarrier 的工作方式更适合您尝试做的事情,Meeting 类看起来像

 public class Meeting{
     CylicBarrier barrier = new CylicBarrier(numberOfEmployees);

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

【讨论】:

  • +1 CyclicBarrier 绝对更合适。 CountDownLatch 通常意味着单独的等待线程和倒计时线程。
  • 我可能应该在问题中提到这一点。会议的构造器获取要参加的员工列表。当一个房间可用时,该房间开始会议并调用会议对象的 startMeeting() 方法,该方法又调用列表中所有 Employee 对象的 meetingRequest() 方法。 @DavidHarkness 使用 CountDownLatch 的原因是因为每次会议都使用了一个新的会议对象。由于会议对象或多或少封装了单个事件,因此使用 CountDownLatch 似乎比使用 CyclicBarrier 更合适。
  • @grg-n-sox 好的,你明白为什么你的程序只会有一个员工到达吗?您需要的是调用具有闩锁await()ing 的方法的员工线程。然后将暂停 Employee 线程,而不是开始会议的主线程。所以这个开始会议的主线程应该通知线程等待会议开始,你所拥有的是线程正在等待所有其他线程等待会议,显然它必须是相反的.
  • 我想我明白你的意思,但你一直指的是开始会议的主线程。但是,在这种情况下,由员工自己决定何时需要召开会议,并且任何初始化会议的人都会尝试将其添加到房间中,如果它是空的,它会立即开始,如果它是满的,会议就会开始。添加到 BlockingQueue。
  • 我想当我提到主线程时,我指的是开始会议的线程。该线程第一次尝试等待员工时,它实际上是在暂停它自己的线程,并且无法取得进一步的进展。因此,正如我提到的,您宁愿通知其他员工参加/等待会议开始。
猜你喜欢
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 2023-03-21
  • 2019-05-07
  • 1970-01-01
相关资源
最近更新 更多