多线程:持续写入共享数据结构并定期清除

我有一个问题,我有多个线程不断写入,例如并发 HashMap。现在,我想定期处理(通过 TimerJob)该哈希图中的所有内容。其他线程仍然可以继续写入(这个新数据将在 Timejob 下次启动时处理)。

我想知道实现这一目标的最佳方法是什么。我正在阅读,这个问题似乎很像Triple Buffer。尽管如此,我并不是非常积极。

有什么想法吗?

编辑:我想以这种方式处理后从地图中删除数据,我最终不会重新处理该数据

编辑:我不需要将数据写入 HashMap/Set。我只需要将它放在一个集合中,我可以在其他线程仍在写入时定期处理该集合。


蓝山帝景
浏览 167回答 2
2回答

HUWWW

我不确定您是否需要地图中的所有数据,或者地图中不再需要的计时器作业处理的数据。如果您只需要计时器作业的快照之类的东西,您可以像这样用新地图切换/替换地图。private volatile ConcurentHashMap map ;public void processByTimerJob(){   ConcurentHashMap oldMap = this.map;   this.map = new ConcurrentHashMap; // everyting new will be stored in new map       oldMap.forEach(.....   //process old map via iteration or whatever you want}

至尊宝的传说

我会使用double buffering和读/写锁。双缓冲通过允许处理换出的映射来减少阻塞。使用读/写锁让我可以确定在我们交换后没有人仍在写入地图。class DoubleBufferedMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {&nbsp; &nbsp; // Used whenever I want to create a new map.&nbsp; &nbsp; private final Supplier<Map<K, V>> mapSupplier;&nbsp; &nbsp; // The underlying map.&nbsp; &nbsp; private volatile Map<K, V> map;&nbsp; &nbsp; // My lock - for ensuring no-one is writing.&nbsp; &nbsp; ReadWriteLock readWriteLock = new ReentrantReadWriteLock();&nbsp; &nbsp; final Lock readLock = readWriteLock.readLock();&nbsp; &nbsp; final Lock writeLock = readWriteLock.writeLock();&nbsp; &nbsp; public DoubleBufferedMap(Supplier<Map<K, V>> mapSupplier) {&nbsp; &nbsp; &nbsp; &nbsp; this.mapSupplier = mapSupplier;&nbsp; &nbsp; &nbsp; &nbsp; this.map = mapSupplier.get();&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Swaps out the current map with a new one.&nbsp; &nbsp; &nbsp;*&nbsp;&nbsp; &nbsp; &nbsp;* @return the old map ready for processing, guaranteed to have no pending writes.&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public Map<K,V> swap() {&nbsp; &nbsp; &nbsp; &nbsp; // Grab the existing map.&nbsp; &nbsp; &nbsp; &nbsp; Map<K,V> oldMap = map;&nbsp; &nbsp; &nbsp; &nbsp; // Replace it.&nbsp; &nbsp; &nbsp; &nbsp; map = mapSupplier.get();&nbsp; &nbsp; &nbsp; &nbsp; // Take a write lock to wait for all `put`s to complete.&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeLock.lock();&nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeLock.unlock();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return oldMap;&nbsp; &nbsp; }&nbsp; &nbsp; // Put methods must take a read lock (yeah I know it's weird)&nbsp; &nbsp; @Nullable&nbsp; &nbsp; @Override&nbsp; &nbsp; public V put(K key, V value) {&nbsp; &nbsp; &nbsp; &nbsp; try{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Take a read-lock so they know when I'm finished.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.lock();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map.put(key, value);&nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.unlock();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void putAll(@NotNull Map<? extends K, ? extends V> m) {&nbsp; &nbsp; &nbsp; &nbsp; try{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Take a read-lock so they know when I'm finished.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.lock();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.putAll(m);&nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.unlock();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @Nullable&nbsp; &nbsp; @Override&nbsp; &nbsp; public V putIfAbsent(K key, V value) {&nbsp; &nbsp; &nbsp; &nbsp; try{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Take a read-lock so they know when I'm finished.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.lock();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map.putIfAbsent(key, value);&nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readLock.unlock();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // All other methods are simply delegated - but you may wish to disallow some of them (like `entrySet` which would expose the map to modification without locks).&nbsp; &nbsp; @Override&nbsp; &nbsp; public Set<Entry<K, V>> entrySet() {&nbsp; &nbsp; &nbsp; &nbsp; return map.entrySet();&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean equals(Object o) {&nbsp; &nbsp; &nbsp; &nbsp; return map.equals(o);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public int hashCode() {&nbsp; &nbsp; &nbsp; &nbsp; return map.hashCode();&nbsp; &nbsp; }&nbsp; &nbsp; // ... The rest of the delegators (left to the student)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java