2016-07-29 3 views
1

Я головная боль с проблемой давным-давно, надеюсь, что какая-то помощь действительно.
Я хочу магазин много Task с ConcurrentSkipListMap который внутренний ConcurrentHashMap как известно как многосегментный замок.
Простой пример кода шоу с Скале (Java также читаемым):
val tasks = new ConcurrentSkipListMap[TaskKey, Task]() см класс просто, как:Как заблокировать бесплатное использование двух ConcurrentHashMap в java/scala?

class TaskKey(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, используемый для сортировки данных, полное 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 
    } 
}) 

любой вопрос радушен, если я что-то пропустил.

+2

Вы могли бы уточнить, что вы подразумеваете под * Когда я использую TaskKey для работы с HashMap, это замечательно, но на самом деле, HashMap может получить доступ с идентификатором. *? Есть несколько подходов к синхронизации двух хэш-карт, но всегда лучше иметь все в одном, как вы предложили изначально. – Augusto

+0

@Augusto, 'get (taskId: String)' используется для получения объекта 'Task'. Я должен получить' TaskKey' перед тем, как получить 'Task'. * Едва * означает, что я не могу использовать' TaskKey' прямо и только могу получить данные с помощью строки taskId. Вот почему я использую два HashMap. – LoranceChen

+0

Я ненавижу такие комментарии сам, но я не могу не спросить. Вы уверены, что вам нужен идентификатор задачи как строка. Может быть, просто использовать TaskKey как идентификатор задачи и иметь только одну карту? –

ответ

0

Я использую очередь сообщений, чтобы сгладить оператор к этим картам. Кроме того, этот способ не обязательно для concurrenthashmap вообще, но для очереди сообщений может потребоваться одновременный вызов.