如何在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变量,completeConcurrentSkipListMap
定义如下:
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用户方面的唯一标记。