java - 使用java ConcurrentSkipListSet add方法时线程卡住

标签 java scala java.util.concurrent

我正在使用 ConcurrentSkipListSet 集合来处理并发运算符。我发现它有时会卡住,用以下代码重现:

import java.util.Comparator
import java.util.concurrent._

object SetDeadLock extends App {
  private val tasks = new ConcurrentSkipListSet[Task](new Comparator[Task](){
    override def compare(o1: Task, o2: Task): Int = {
      val compare = (o1.systemTime - o2.systemTime).toInt
      if (compare == 0) 1 else compare  //distinct same time task
    }
  })

  for(i <- 1 to 20) {
    tasks.add(Task())
    println(s"added - $i")
  }

  case class Task() {
    val systemTime = System.currentTimeMillis()
  }
}

输出

added - 1
added - 2

它可能卡在其他地方,此外,比较器自定义排序数据方法特别是它们是相同的(因为Set不支持相同元素)并且所有Task都是新实例,它不应该与其他。

使用jstack cmd,主线程卡住

at java.util.concurrent.ConcurrentSkipListMap.findPredecessor(ConcurrentSkipListMap.java:685)

这是一个错误还是我只是误导了一些原则?

感谢任何帮助或建议。

更新
我刚刚尝试将 if (compare == 0) 1 else Compare 修改为 if (compare == 0) -1 else Compare,令人惊讶的是,我工作得很好!

有谁能解释一下它是如何工作的吗?源代码对我来说很难(我想很多人都同意我的观点),毕竟jdk为机器执行速度而不是代码阅读器做了很多工作。

终于
为了避免尴尬的情况,只需对 comparator 做一些不同的因素来匹配 Set 的语义,例如附加一个随机值。但我认为最好找到另一个真实的值适合 Collection 。

几天前,我发现一个好主意,当 systemTime 等于时,使用 hashCode 作为第二次验证。希望有帮助~

最佳答案

您的比较器不稳定。我认为当不同的调用给出不一致的结果时,ConcurrentSkipListMap 不会表现得很好。例如,根据您的调用方式,您可以在代码中同时考虑 a < b 和 b < a。

关于java - 使用java ConcurrentSkipListSet add方法时线程卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37558703/

相关文章:

java - Excel 中 Java 中的 Selenium WebDriver 中的 2 个接口(interface)之间如何进行向下转型/向上转型

java - 升级tomcat 7.0.59到7.0.61 : Cannot create a session after the response has been committed

scala - Stackless Scala 播放框架运行时错误

java - java中的DelayQueue - 未按预期工作

java - ConcurrentSkipListSet,添加方法在 Java 8 中失败

java - 在java中检查进程何时完成?

java - CrudRepository 自定义方法实现?

scala - => 、 ()=> 和 Unit=> 之间有什么区别

postgresql - scalikeJDBC + postgres - 找不到合适的驱动程序

java - Guava MapMaker().weakKeys().makeMap() 与 WeakHashMap