使用最后一种方法实现 Treeset 上的并发

Jua*_*ega 2 java collections concurrency

我想实现一个 bean,其中我有一个TreeSet按排序顺序存储整数的 bean。使用此方法的唯一方法TreeSetaddValue向集合中添加一个新整数,以及使用中的getHighestValue方法返回集合中的最后一个值。last()SortedSet

这里有并发问题吗?我没有使用任何显式迭代器,因此在获取最高值时不应该出现任何并发问题,但我不知道如果ConcurrentModificationException两个线程尝试添加并获取最高值,最后一个方法是否会抛出任何或任何其他异常同一时间。

dim*_*414 6

是的,假设多个线程正在与该集合交互,并且至少有一个线程正在修改,则存在并发问题。特别是,您提到多个线程执行添加操作,这肯定会导致问题 - 但更糟糕的是,它们可能不会引发ConcurrentModificationExceptions。

的目的ConcurrentModificationException是提醒您明显错误的并发问题,例如在迭代集合时尝试从集合中删除项目(在这种情况下,不清楚集合应该做什么)。但是,只有当集合意识到错误的修改时才能引发异常。由于集合不是线程安全的,因此它明确不能保证多线程操作能够正确完成,并且您应该自己手动保护集合。

Collections.synchronizedSortedSet()最简单但效率最低的方法是在使用之前将集合包装起来,即:

SortedSet synchronizedSet = Collections.synchronizedSortedSet(new TreeSet());
Run Code Online (Sandbox Code Playgroud)

这确保每个方法调用都将串行完成,也就是说,它们将阻塞等待任何早期的调用完成。然而,这样一来,您基本上就失去了多线程的大部分好处。

另一种选择是使用显式线程安全SortedSet,即ConcurrentSkipListSet

此实现提供了、、 和操作及其变体log(n)的预期平均时间成本。插入、删除和访问操作由多个线程同时安全地执行。containsaddremove

此实现允许您从多个线程与集合进行交互,而无需进一步担心。这并不是说这是实现您正在寻找的行为的最佳方式,但是考虑到您所描述的内容 - 从多个线程添加和访问排序集中的最大值 - 这就是您正在寻找的。

另请参阅:ConcurrentSkipListSet 何时有用?