LoranceChen LoranceChen - 1 year ago 88
Java Question

Thread stuck when use java ConcurrentSkipListSet add method

I'm using ConcurrentSkipListSet collection to deal with concurrent operator. I find it will stuck sometimes, reproduct with this code:

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) {
println(s"added - $i")

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


added - 1
added - 2

It perhaps stuck at others, besides, the comparator custom sort data method especially they are same (because Set not support same element) and all
is new instance, it shouldn't be conflict with others.

cmd, the main thread stuck

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

does it was a bug or I just misleading some principle?

Thanks any help or advise.


I just now try modify
if (compare == 0) 1 else compare
if (compare == 0) -1 else compare
, surprising, I works well!

Does anyone could clarify how it work? Source code its difficult for me(and I think many people agree with me), after all, jdk do many works for machine execute speed not for code reader.


To avoid the awkward situation just make some different factor to
which match
's semantics, such as appends a random value.But I think its will be better find another real suitable collection.

With a few days ago, I find a good idea to use hashCode as second verify when systemTime equals. hope helpful~

Answer Source

Your comparator is not stable. I don't think ConcurrentSkipListMap promises to behave nicely when different calls give inconsistent results. For instance, depending on how you call, you can think both a < b and b < a at the same time with your code.