如何在java/scala中锁定免费使用两个ConcurrentHashMap?

如何在java/scala中锁定免费使用两个ConcurrentHashMap?,java,multithreading,scala,concurrenthashmap,Java,Multithreading,Scala,Concurrenthashmap,这个问题我早就头疼了,真的希望能有所帮助。 我想用ConcurrentSkipListMap存储许多Task,其内部是ConcurrentHashMap,称为多段锁。 scala的简单示例代码(java也可读): val tasks=new ConcurrentSkipListMap[TaskKey,Task]() 将简单类定义为: 类任务键(id:String,systemTime:Long) 用于标识任务的TaskKey类是唯一的,任务如下所示: trait Task { val tas

这个问题我早就头疼了,真的希望能有所帮助。
我想用
ConcurrentSkipListMap
存储许多
Task
,其内部是
ConcurrentHashMap
,称为多段锁。
scala的简单示例代码(java也可读):
val tasks=new ConcurrentSkipListMap[TaskKey,Task]()
将简单类定义为:

类任务键(id:String,systemTime:Long)

用于标识任务的TaskKey类是唯一的,任务如下所示:

trait Task {
  val taskId: TaskKey //account and custom name
  def execute(): Unit //do the task
}
当我使用TaskKey操作我的HashMap时,我的HashMap很难使用id访问。因此,我必须定义另一个ConcurrentHashMap来存储id到TaskKey的映射:
val-auxiliaryMap=new-ConcurrentHashMap[String,TaskKey]()

让我们考虑一个添加和删除操作:

def get(taskId: String) = {
  Option(auxiliaryMap.get(taskId)).flatMap{x => //try get TaskKey
    //if TaskKey exist, try get it.
    Option(tasks.get(x)) //make null to None
  }
}

def remove(taskId: String) = {
  Option(auxiliaryMap.remove(taskId)).flatMap{ x => //try get TaskKey
    //if TaskKey exist, try remove it.
    Option(tasks.remove(x)) //make null to None
  }
}
显然,尽管这两个映射都是线程安全的,但包装器使数据不一致。如果使用锁,多段映射将变得毫无意义。如何处理这个问题使两个ConcurrentHashMap很好地工作

此外,TaskKey包含一个用于对数据排序的systemTime变量,complete
ConcurrentSkipListMap
定义如下:

val tasks = new ConcurrentSkipListMap[TaskKey, Task](new Comparator[TaskKey]() {
  override def compare(o1: TaskKey, o2: TaskKey): Int = {
    val compare = (o1.systemTime - o2.systemTime).toInt

    if (compare == 0) {
      o1.hashCode() - o2.hashCode()
    } else compare //distinct same time task
  }
})

如果我遗漏了什么,欢迎提出任何问题。

我正在使用消息队列将运算符展平到这些映射。此外,这种方式根本不需要concurrenthashmap,但消息队列可能需要concurrentqueue。

我正在使用消息队列将运算符展平到这些映射。此外,这种方式根本不需要concurrenthashmap,但消息队列可能需要concurrentqueue。

您能否澄清一下,当我使用TaskKey操作我的HashMap时,您的意思是什么?这很好,但实际上,HashMap只能用id访问。?有一些方法可以同步2个hashmap,但最好按照您最初的建议,将所有内容都放在一个hashmap中。@Augusto,
get(taskId:String)
用于获取
任务
对象。在获取
任务
之前,我必须获取
任务键
。*勉强*意味着我不能直接使用
任务键
,只能获取带有taskId字符串的数据。这就是为什么我要使用两个HashMap。我自己讨厌这样的评论,但我忍不住要问。您确定需要任务id作为字符串吗。也许只是使用TaskKey作为任务id,并且只有一个地图?@ArtemMalinko,你的地图非常小心,谢谢你注意到这一点。但是我不能简单地使用TaskKey。在这种情况下,我简化了我想做的一些逻辑。简而言之,有一个
cancel(id:String)
操作来决定删除一个任务,但任务有一个
nextTask
方法,在任务完成时可以生成新任务。具有不同任务键的新任务具有相同的
id
和不同的
systemTime
。为了支持取消生成的任务,较旧的TaskKey毫无意义。因此,id是API用户对任务的唯一标记。您能否澄清一下,当我使用TaskKey操作HashMap时,您的意思是什么?我的HashMap很好,但实际上,HashMap只能用id访问。?有一些方法可以同步2个hashmap,但最好按照您最初的建议,将所有内容都放在一个hashmap中。@Augusto,
get(taskId:String)
用于获取
任务
对象。在获取
任务
之前,我必须获取
任务键
。*勉强*意味着我不能直接使用
任务键
,只能获取带有taskId字符串的数据。这就是为什么我要使用两个HashMap。我自己讨厌这样的评论,但我忍不住要问。您确定需要任务id作为字符串吗。也许只是使用TaskKey作为任务id,并且只有一个地图?@ArtemMalinko,你的地图非常小心,谢谢你注意到这一点。但是我不能简单地使用TaskKey。在这种情况下,我简化了我想做的一些逻辑。简而言之,有一个
cancel(id:String)
操作来决定删除一个任务,但任务有一个
nextTask
方法,在任务完成时可以生成新任务。具有不同任务键的新任务具有相同的
id
和不同的
systemTime
。为了支持取消生成的任务,旧的TaskKey是没有意义的。因此,id是任务在API用户方面的唯一标记。