Java 集合的原子复制和清除

Atomic copy-and-clear on Java collection

我知道类似的问题经常被问到,但我找不到任何可以帮助我的东西。

情况是这样的:

问题是:如何复制(我认为最好在副本上工作)第二个工人的集合,然后清除原始集合以确保我们不会丢失任何东西(第一个工人一直在写) 但不要尽可能短地锁定原始集合?

谢谢

如果您使用 LinkedBlockingQueue rather than a plain HashSet. Have the producer add elements to the queue, and the consumer can use drainTo 等专门构建的并发工具根据需要从队列中批量提取元素,这种事情会容易得多。不需要任何同步,因为 BlockingQueue 实现被设计为线程安全的。

Ian 的 LinkedBlockingQueue 解决方案是最简单的。

为了在单生产者单消费者场景中获得更高的吞吐量(可能与延迟权衡),您可能需要考虑 java.util.concurrent.Exchanger

中的示例

交换后,您现在拥有整个 collection 自己。

适合我

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyClass {

  private final Map<String, Integer> cachedData = new ConcurrentHashMap<>();
  private final ReadWriteLock lock = new ReentrantReadWriteLock();
  private final Lock sharedLock = lock.readLock();
  private final Lock copyAndFlushLock = lock.writeLock();

  public void putData(String key, Integer value) {
    try {
      sharedLock.lock();
      cachedData.put(key, value);
    } finally {
      sharedLock.unlock();
    }
  }

  public Collection<Integer> copyAndFlush() {
    try {
      copyAndFlushLock.lock();

      Collection<Integer> values = cachedData.values();
      cachedData.clear();

      return values;
    } finally {
      copyAndFlushLock.unlock();
    }
  }
}