使用java ConcurrentSkipListSet添加方法时线程卡住了

时间:2016-06-01 03:01:46

标签: 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都是新实例,它不应该与其他实例冲突。 / p>

jstack cmd,主线程卡住了

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

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

感谢任何帮助或建议。

更新
我现在尝试修改if (compare == 0) 1 else compareif (compare == 0) -1 else compare,令人惊讶的是,我运作良好!

有没有人可以澄清它是如何工作的?源代码对我来说很难(我想很多人都同意我的观点),毕竟,jdk为机器执行速度做了很多工作而不是代码阅读器。

最后
为了避免尴尬的情况,只需要对comparator的{​​{1}}语义进行一些不同的因素,例如附加一个随机值。但我认为它会更好地找到另一个真正合适的集合。​​

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

1 个答案:

答案 0 :(得分:1)

您的比较器不稳定。当不同的调用给出不一致的结果时,我不认为ConcurrentSkipListMap承诺表现得很好。例如,根据您的呼叫方式,您可以同时考虑&lt; b和b&lt; a与您的代码同时进行。