这篇文章的摘要:我有一组订购的商品,其顺序可能会随着时间的推移而改变。我需要能够从多个线程迭代这个集合,每个线程可能还想更新项目的顺序。
例如,多个线程需要以某种任意排序的顺序访问String
键。它们的字符串不是根据其自然顺序排序,而是根据一些可能更改的值排序(因此,是一个自定义的比较器)。我最初的实现是使用 TreeSet 并在其上进行同步。如果任何键需要重新排序,线程将从映射中删除该键,更新比较值,然后重新插入该键。为了实现这一点,键是 native String
,但比较器可以访问值。这是一种奇怪的安排,其中键的顺序可能会随着时间的推移而改变,但由于更改后的键总是在更改时被删除并重新插入,因此它似乎有效。 (我想如果 String
被包装在另一个对象中也可以工作。)
我最近意识到 ConcurrentSkipListSet
/ConcurrentSkipListMap
实现基本上是线程安全的排序集(分别是映射。)似乎我现在可以迭代键,而不必锁定整个数据结构。但是,有没有一种方法可以使用它们以原子方式删除一个键并将其替换为另一个键,就像我上面所做的操作一样,以便其他迭代线程不会错过该项目,并且不必使用 synchronize
block ?
如果有人可以为此类操作提出更好的数据结构,我也洗耳恭听!
最佳答案
is there a way I can use them to atomically remove a key and replace it with another, like the operation I was doing above, so that other iterating threads don't miss the item, and without having to use synchronize blocks?
简短的回答是否定的。如果您需要删除并重新插入,据我所知,没有原子方法可以对任何集合执行此操作。
也就是说,一种可能是您在将项目从跳过列表中删除之前重新插入该项目。这会导致重复,但可能比丢失条目更容易处理。您可以在更改对象后重新插入它,这样它就会以不同的方式排序。这假设该对象也将是不相等的。但如果处理列表的其他线程无法处理重复项,那么我认为您是 SOL。
关于java - 在 ConcurrentSkipListMap/ConcurrentSkipListSet 中重新排序键的原子方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15507418/