阻止对象使用什么?

时间:2013-10-15 12:22:00

标签: java multithreading blocking

我需要一个阻塞对象来触发某些事件。 (单个)消费者应该等待触发发生。然后它做了一些事情。然后它再次等待触发器。 触发器由多个不同的线程(生产者)激活。但生产者不会产生任何数据。这种触发器的语义含义是:“消费者必须做某事”(例如重新计算某些值,因为基础数据已更改)。 这意味着即使触发器被多次激活,它也应该被消费者视为单个触发器。

我考虑使用CountDownLatchArrayBlockingQueue,但它们似乎不合适。

这是我想要使用的触发器构造:

public class Trigger{
  private final MagicBlockingObject blockingLatch;

  public void trigger(){
     //activate the blockingLatch, so that a call to waitForTrigger() returns
  } 

  public void waitForTrigger(){
    //read from the blockingLatch. This should block until trigger() is called.
  }
}

关于MagicBlockingObject使用什么的任何想法?

BlockingQueue似乎合适,但如果队列已经填满,我没有找到将其限制为单个内容对象而不阻塞生产者的方法。

3 个答案:

答案 0 :(得分:2)

您可以使用容量为1的ArrayBlockingQueue解决此问题:

public class Trigger{
  private final ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);

  public void trigger(){
     queue.offer("foo");
  } 

  public void waitForTrigger(){
    queue.take();
  }
}

答案 1 :(得分:1)

这样的简单解决方案有什么问题:

public class Trigger {
    private final Object blockingLatch = new Object();

    public void trigger() {
        //activate the blockingLatch, so that a call to waitForTrigger() returns
        synchronized(blockingLatch){
            blockingLatch.notify();
        }
    }

    public void waitForTrigger() throws InterruptedException {
        //read from the blockingLatch. This should block until trigger() is called.
        synchronized(blockingLatch){
            blockingLatch.wait();
        }
    }
}

Consumer将调用waitForTrigger()并阻塞直到生产者没有调用trigger()。如果消费者没有被阻止,那么生产者调用trigger()不会影响任何事情。

答案 2 :(得分:0)

java.util.concurrent有很多不错的实用程序。 waitnotify应该被视为过时。

如果我了解您的问题,您可以尝试使用Semaphore

public class Blocking {
    private final Semaphore openTasks = new Semaphore(0);
    public void addTask() {
        // add 1
        openTasks.release();
    }
    public void takeAllTasks() throws InterruptedException {
        int immediately = openTasks.drainPermits();
        if (immediately > 0) {
            // there was a task, no need to wait
            return;
        }
        // wait for task
        openTasks.acquire();
        // ensure we leave this method without leaving permits
        openTasks.drainPermits()
    }
}

无限制的生产者可以向信号量添加“许可证”,而您的消费者只需将其全部或等待至少一个出现。