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();
}
}
}
我知道类似的问题经常被问到,但我找不到任何可以帮助我的东西。
情况是这样的:
- 一名工作人员正在向集合中添加元素
- 第二个正在等待一段时间(元素的成熟度)或特定大小的集合,然后开始它的工作。
问题是:如何复制(我认为最好在副本上工作)第二个工人的集合,然后清除原始集合以确保我们不会丢失任何东西(第一个工人一直在写) 但不要尽可能短地锁定原始集合?
谢谢
如果您使用 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();
}
}
}