java - 在 Java 中阻塞并同时释放可变数量的线程

标签 java concurrency

我正在用 Java 构建一个缓冲区,它将收集许多线程请求的写操作,并将它们作为一个组刷新,比如说每秒一次。我想给它一个名为 waitForFlush 的方法,该方法将阻塞调用它的线程,直到下一个刷新事件完成。同时,一个单独的独立线程正在循环中刷新和 hibernate 。所以我基本上是在寻找一种并发结构或模式,允许许多线程在特定点阻塞,然后同时释放它们,我发现 Java 的内置并发原语都不是真正匹配的.到目前为止我想出的最好的是 wait/notifyAll,如下所示:

public class Buffer {

  private volatile long lastFlushTime = System.currentTimeMillis();
  private final Object flushMonitor = new Object();

  public void waitForFlush() {
    long entryTime = System.currentTimeMillis();

    synchronized(flushMonitor) {
      while(lastFlushTime <= entryTime) {
        flushMonitor.wait();
      }
    }
  }

  public void flush() {
    // do flush stuff here
    synchronized(flushMonitor) {
      lastFlushTime = System.currentTimeMillis();
      flushMonitor.notifyAll();
    }
  }
}

虽然我认为这在实践中会很好地工作,但 waitForNotify() 中的同步块(synchronized block)对我来说仍然有些不完美。理想情况下,对于此用例,您可以调用 wait() 而无需同步关联的对象,并且所有被阻塞的线程都将在 notifyAll( ) 被调用,而不是一个一个地退出同步块(synchronized block)。

所以,一般来说,有没有比我上面概述的更好的方法来阻止和同时释放可变数量的线程(我认为 Semaphore 和 CountDownLatch 类只适用于固定数量的线程)?

最佳答案

尽管正如 Marko Topolnik 和 munyengm 提到的那样,CountDownLatch 只适用于一次性情况。它在循环场景中失败(即每个 CDL 只能 await & countDown 一次)。然后您可能会考虑使用 CyclicBarrier,但在您的情况下会失败,因为您需要知道正在使用的线程数。

如果你可以使用 Java 7,我推荐 Phaser .您可以让单个线程向多个等待线程发送信号并重用。

final Phaser phaser = new Phaser(1);//register one thread to arrive

 public void waitForFlush() {
    int phase = phaser.getPhase();
    phaser.awaitAdvance(phase);    
 }

  public void flush() {
      lastFlushTime = System.currentTimeMillis();
      phaser.arrive(); //signals all waiting threads on the current phase and will increment the phase by 1
  }

关于java - 在 Java 中阻塞并同时释放可变数量的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11375683/

相关文章:

java - 来自 Android 的 Yelp v2 API 使用 SignPost oauth libs 说签名无效

c - 多线程合并排序无法正确对数组进行排序

multithreading - 在pthread中,如何可靠地将信号传递给另一个线程?

c++ - 使用 std::mutex、std::condition_variable 和 std::unique_lock

使用 WSHttpBinding 时 WCF 并发请求堆积在服务器上

java - 为什么在构造函数中赋值时,clone()函数显示不兼容的类型?

java - Android 中的文件/数据库在线同步

ios - 用于保存到核心数据的 NSPersistentContainer 并发

java - Neo4j-reco : Engine FriendsComputingEngine wasn't found on the classpath

java - 警告 : while trying to convert java byte[] to C unsigned char*