Я давно мучаюсь с этой проблемой, надеюсь на какую-то помощь.
Я хочу хранить много Task
с ConcurrentSkipListMap
, внутреннее значение которого ConcurrentHashMap
известно как многосегментная блокировка.
Простой пример кода, показанный со scala (java также читаем ):val tasks = new ConcurrentSkipListMap[TaskKey, Task]()
ссылаться на простой класс как:
class TaskKey(id: String, systemTime: Long)
Класс TaskKey, используемый для идентификации Task, уникален, и Task выглядит следующим образом:
trait Task {
val taskId: TaskKey //account and custom name
def execute(): Unit //do the task
}
Когда я использую TaskKey для работы, моя HashMap невозможна, но на самом деле HashMap едва может получить доступ с идентификатором. Итак, я должен определить другой ConcurrentHashMap для хранения сопоставления идентификатора с 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 содержит системную переменную Time, используемую для сортировки данных, полное 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
}
})
любые вопросы приветствуются, если я что-то пропустил.
get(taskId: String)
используется для получения объектаTask
. Я должен получитьTaskKey
, прежде чем получитьTask
. *Едва* означает, что я не могу использоватьTaskKey
напрямую и могу получать данные только со строкой taskId. Вот почему я использую два HashMap. - person LoranceChen   schedule 29.07.2016cancel(id: String)
для решения об удалении задачи, но у задачи есть методnextTask
, который может генерировать новую задачу, когда она будет выполнена. Новая задача с другим TaskKey, который имеет тот жеid
и другойsystemTime
. Чтобы поддерживать отмену сгенерированной задачи, старый TaskKey не имеет смысла. Итак, id — это уникальная метка для задачи с точки зрения пользователя API. - person LoranceChen   schedule 29.07.2016