implementieren Sie-Ihre-eigenen-blocking queue in java
Ich weiß, diese Frage wurde gestellt und beantwortet viele Male zuvor, aber ich konnte einfach nicht herausfinden, einen trick auf die Beispiele rund um das internet, wie diese oder dass ein.
Beide Lösungen prüfen, für die leere der blockierenden Warteschlange array/queue/linkedlist zu notifyAll
wartenden threads in put()
- Methode und vice versa im get()
Methoden. Ein Kommentar in das zweite Glied betont in dieser situation und erwähnt, dass das nicht notwendig.
Also die Frage ist; auch scheint Es ein wenig seltsam für mich, zu überprüfen, ob die Warteschlange leer | voll benachrichtigt alle wartenden threads. Irgendwelche Ideen?
Vielen Dank im Voraus.
- Teil der Ausstellung bezieht sich auf die Schwierigkeit, mit
wait
undnotify
richtig in concurrent Programmen; Zitat von Joshua Bloch, Sie sind wie "low-level (Assembler) des concurrent programming." Er plädiert für die VerwendungnotifyAll
und dass wartende threads sollten immer eine Prüfung innerhalb einer Schleife, wenn benachrichtigt, so dass Sie halten können warten als nötig. Wirklich, man sollte Sie einfach nicht verwenden Sie wait/notify, und, statt immer planen zu verwenden, das höhere Niveau der konkurrierenden APIs in Java SE 5. Anstatt threads und wait/notify, design konkurrierenden apps in Bezug auf die Aufgaben und Testamentsvollstrecker. - yep, ich bin ganz mit Ihnen einverstanden, oldies but goodies: keine Notwendigkeit, das Rad neu zu erfinden. Aber denke, wir müssen warten und notifyAll für diesen Fall. Ich weiß, dass wait() sollte verwendet werden, innerhalb einer Schleife, alles erklärt in den javadocs (spurious wakeups) : docs.oracle.com/javase/6/docs/api/java/lang/.... Aber was der hack über, die Bedingungen für die Benachrichtigung? Das ist der Punkt, den ich nicht bekommen konnte.
- Siehe hier - Sie verwenden
ReentrantLock
undCondition
s,nichtwait
/notify
überhaupt. - wir sind in Bewegung aus dem Rahmen problem!!! Ich schaue für die eigentlichen Implementierungen, aber das ist wohl die naive Weise für eine selbst implementierte Warteschlange blockieren, und warum gibt es gleich - "wenn" - Bedingungen in den verschiedenen Lösungen? Nur ein copy paste? Unbewusste Codierung? 🙂
- Ich war Lesung durch jenkov ist tutorials, und aus meinem Verständnis, die
if (this.queue.size() == this.limit) { notifyAll(); }
Hinzugefügtdeque
da, die threads wurden einreihen geht zu wait() nur bei der Größe hat das limit. Wenn einer der threads, deques das element, wenn die Größe voll ist, soll Sie informieren die wartenden threads. Korrigieren Sie mich, wenn ich falsch Liege 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich weiß, das ist eine alte Frage, die von jetzt, aber nach dem Lesen der Frage und Antworten konnte ich nicht helfen, mein selbst, ich hoffe, Sie finden diese nützlich.
In Bezug auf die überprüfung, ob die queue tatsächlich voll ist oder leer vor, bevor er die anderen wartenden threads, Sie sind nicht etwas, was sowohl die Methoden
put (T t)
undT get()
sind beidesynchronized
Methoden, was bedeutet, dass nur ein thread kann geben Sie eine der folgenden Methoden, zu einer Zeit, aber das wird nicht verhindern, dass Sie arbeiten zusammen, so dass, wenn ein thread-ein eingegeben hatput (T t)
Methode, die ein anderer thread b kann immer noch geben Sie und starten Sie das ausführen der Anweisungen inT get()
Methode, bevor thread a beendet wurdeput (T t)
, und sodouble-checking
design machen die Entwickler fühlen sich ein wenig sicherer, weil man nicht wissen kann, wenn zukünftige cpu-Kontextwechsel, wenn oder wenn geschehen wird.Besser und eine weitere empfohlene Methode ist die Verwendung
Reentrant Locks
undConditions
://Ich habe bearbeitet den Quellcode von diesem link
Mit diesem Ansatz gibt es keine Notwendigkeit für
double checking
, weil dielock
Objekt ist geteilt zwischen den beiden Methoden, was bedeutet, dass nur ein thread a oder b eingeben können, diese Methoden zu einer Zeit, im Gegensatz zu synchronisierten Methoden, die schafft verschiedenen Monitoren, und nur diese threads warten, weil die Warteschlange voll ist, werden Sie benachrichtigt werden, wenn es mehr Raum, und das gleiche gilt für threads warten, weil die Warteschlange leer ist, führt dies zu einer besseren cpu-Auslastung.finden Sie weitere detaillierte Beispiele mit source-code hier
Ich denke logisch, es gibt keinen Schaden tun die extra-check vor
notifyAll()
.Können Sie einfach
notifyAll()
sobald Sie setzen/Holen etwas aus der Warteschlange. Alles weiterhin funktioniert, und der code ist kürzer. Jedoch, es ist auch kein Schaden, die überprüfen, ob jemand potenziell zu warten (mit der überprüfung, ob das schlagen der Grenze der Warteschlange), bevor Sie Sie aufrufennotifyAll()
. Diese zusätzliche Logik spart unnötigenotifyAll()
Aufrufe.Es kommt nur darauf an, Sie wollen eine kürzere und sauberer code, oder Sie wollen, dass Ihr code effizienter ausgeführt werden. (Habe nicht geschaut in
notifyAll()
's Umsetzung. Wenn es eine Billig-operation, wenn es niemand warten, der performance-Gewinn kann nicht offensichtlich sein, für die zusätzliche Prüfung sowieso)Der Grund, warum die Autoren verwendeten
notifyAll()
ist einfach: Sie hatten keine Ahnung, ob oder nicht es notwendig war, und so entschieden Sie sich für die "sicherere" option.Im obigen Beispiel würde es ausreichen, rufen Sie
notify()
als für jedes einzelne element Hinzugefügt, nur einen einzigen thread warten, bedient werden können, unter allen Umständen.Dies wird noch deutlicher, wenn in Ihrer Warteschlange hat die option zum hinzufügen mehrerer Elemente in einem Schritt wie
addAll(Collection<T> list)
wie in diesem Fall mehr als ein thread wartet auf eine leere Liste bedient werden konnten, um genau zu sein: es werden so viele threads wie die Elemente Hinzugefügt wurden.Den
notifyAll()
jedoch führt zu einem Mehraufwand in den speziellen single-element-Fall, wie viele threads geweckt unnötig und müssen deshalb eingeschläfert werden wieder blockiert-Warteschlange-Zugang in der Zwischenzeit. So ersetztnotifyAll()
mitnotify()
würde die Geschwindigkeit verbessert in diesem speziellen Fall.Aber dann nicht mit warten/Benachrichtigen und synchronisiert, sondern verwenden das concurrent-Paket würde die Erhöhung der Geschwindigkeit durch eine Menge mehr als jeder smart-wait/notify-Implementierung könnte jemals.