2016-07-29 19 views
1

Ich Kopfschmerzen mit dem Problem vor langer Zeit, hoffe, einige Hilfe wirklich.
Ich möchte speichern viele Task mit ConcurrentSkipListMap welche innere ist ConcurrentHashMap als Multi-Segment-Sperre bekannt.
Die einfache Show Beispielcode mit scala (java auch lesbar):
val tasks = new ConcurrentSkipListMap[TaskKey, Task]() Klasse beziehen sich einfach wie:wie frei zu sperren, verwenden Sie zwei ConcurrentHashMap in Java/Scala?

class TaskKey(id: String, systemTime: Long)
TaskKey Klasse Identität Aufgabe ist weltweit einzigartig und die Aufgabe wie folgt:

trait Task { 
    val taskId: TaskKey //account and custom name 
    def execute(): Unit //do the task 
} 

Wenn ich TaskKey zum Betrieb meiner HashMap verwenden, ist Rost, aber eigentlich kann die HashMap mit ID kaum zugreifen.So muss ich eine andere ConcurrentHashMap definieren, um die Zuordnung von ID zu TaskKey zu speichern:
val auxiliaryMap = new ConcurrentHashMap[String, TaskKey]()
Lassen Sie uns ein Add betrachten und entfernen betreiben:

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 
    } 
} 

Offensichtlich obwohl beide Map Thread-sicher ist, die Wrapper-Daten machen keine Konsistenz. Wenn ich eine Sperre verwende, wird die Karte mit mehreren Segmenten bedeutungslos. Wie kann ich mit dem Problem umgehen, dass zwei ConcurrentHashMap funktionieren?

Außerdem enthält die TaskKey eine Systemtime Variable verwendet, um Daten zu sortieren, komplett ConcurrentSkipListMap wie folgt definieren:

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 
    } 
}) 

jede mögliche Frage ist willkommen, wenn ich etwas zu verpassen.

+2

Könntest du klarstellen, was du damit meinst * Wenn ich TaskKey zum Bedienen meiner HashMap benutze ist das toll aber eigentlich kann die HashMap mit id kaum zugreifen. Es gibt einige Ansätze, um 2 Hashmaps zu synchronisieren, aber es ist immer besser, alle in einem zu haben, wie Sie es ursprünglich vorgeschlagen haben. – Augusto

+0

@Augusto, 'Get (taskId: String)' verwendet, um ein 'Task' Objekt zu bekommen.Ich muss' TaskKey' bekommen, bevor 'Task'. * Kaum * bedeutet, ich kann' TaskKey' nicht direkt verwenden und nur bekommen Daten mit einer taskId Zeichenfolge. Deshalb verwende ich zwei HashMap. – LoranceChen

+0

Ich hasse solche Kommentare selbst, aber ich kann nicht helfen zu fragen. Sind Sie sicher, dass Sie die Aufgaben-ID als String benötigen? Vielleicht einfach TaskKey als Task-ID verwenden und nur eine Map haben? –

Antwort

0

Ich benutze Nachrichtenwarteschlange, um den Operator zu diesen maps.besides, muss dieser Weg keine Concurrenthashmap überhaupt, aber Nachrichtenwarteschlange möglicherweise eine gleichzeitige Warteschlange benötigen.