0

我有以下场景:多个事件来自一个源,每个事件都有不同的类型。我需要按顺序对同一类型的每个事件执行某些操作,如果是其他类型,则并行执行。意义:

来自源的事件:A1、A2、B1、A3、B2、C1

  • 侦听器 A,必须将 A1、A2 和 A3 排队,并在单个线程中按此顺序处理它们
  • 侦听器 B 与 A 相同,并行,在不同的线程中
  • 侦听器 C 与 B 相同,并行,在不同的线程中

我在做什么来实现这一目标?一般来说,我对每种类型的事件都有一个监视器,我用一个新线程初始化,然后调用 wait()。每个监视器都有一个队列。

Monitor.java(实现可运行)

public void run(){
  while(!killed){
    synchronize(this){     
      while(this.stopped){
        wait(); //it waits here when initialized, waiting for the first event
      }

      while(eventQueue.size() > 0){
        //do something with the event
      }

      //i set the flag stopped = true again to wait for the next event
      this.stopped = true;
    }
  }
}

当一个事件到达时,我将它添加到队列中,然后通知()监视器,这样它就会中断

public void awake(Event event){
  synchronize(this){
    eventQueue.add(event);
    this.stopped = false;
    notify();
  }
}

“killed”标志用于保持线程处于活动状态,直到满足某些条件。然后,我将killed标志设置为true并通知监视器结束线程。

我的问题是当我运行一组事件时,有时线程不会通过 notify() 唤醒。有时处理 10 个事件中的 10 个,有时是 10 个事件中的 8 个,依此类推。

我一直在寻找并发 api 为我的问题寻找一些替代方案,但我找不到任何好的东西。你们能给我一些关于如何面对这个问题的建议吗?

我希望我能很好地解释我的问题。如果没有,请询​​问。

提前致谢。

4

1 回答 1

5

“killed”标志用于保持线程处于活动状态,直到满足某些条件。然后,我将killed标志设置为true并通知监视器结束线程。

首先,我会认真考虑将您的代码切换为BlockingQueue使用LinkedBlockingQueue. 您仍然可以使用该killed标志(必须是voltilebtw),但是通过使用BlockingQueue所有的信号都是为您处理的。您所做的就是调用put()将内容添加到队列并take()从中读取。然后,您不需要使用synchronized,waitnotify. 你根本不需要stopped旗帜。见下文。

while (!killed) {
   Event event = eventQueue.take();
   ...

我的问题是当我运行一组事件时,有时线程不会通过 notify() 唤醒。有时处理 10 个事件中的 10 个,有时是 10 个事件中的 8 个,依此类推。

就您当前的代码出了什么问题而言,我没有看到任何问题,但魔鬼在细节中。要记住的一件事是,如果线程 A 调用notify()然后线程 B 调用,wait()通知已丢失。我认为您想要执行以下操作:

while(!killed){
   Event event;
   synchronized (this) {
       // wait until where is something in the queue
       while(eventQueue.isEmpty()){
           this.wait();
       }
       event = eventQueue.get();
   }
   // work with event
   ...

这只有在队列为空且不需要stopped布尔值的情况下才会如此。

于 2013-06-25T13:39:06.313 回答