Ich habe mich für "drainTo" entschieden, weil ich den Status des temporären Punkts von "LinkedBlockingQueue" in meinem Unternehmen abrufen musste.
drainTo
ist
Entfernt alle verfügbaren Elemente aus dieser Warteschlange und fügt sie der angegebenen Sammlung hinzu.
Es ist eine Methode namens.
Wenn Sie sich jedoch die Hilfe ansehen,
Das Verhalten dieser Operation ist undefiniert, wenn die angegebene Auflistung während der Operation geändert wird.
Es gab einen unangenehmen Satz, und ich untersuchte, ob es ein Problem gab.
30.11.2017 Nachtrag
LinkedBlockingQueue.java
/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
boolean signalNotFull = false;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
int n = Math.min(maxElements, count.get());
// count.get provides visibility to first n Nodes
Node<E> h = head;
int i = 0;
try {
while (i < n) {
Node<E> p = h.next;
c.add(p.item);
p.item = null;
h.next = h;
h = p;
++i;
}
return n;
} finally {
// Restore invariants even if c.add() threw
if (i > 0) {
// assert h.item == null;
head = h;
signalNotFull = (count.getAndAdd(-i) == capacity);
}
}
} finally {
takeLock.unlock();
if (signalNotFull)
signalNotFull();
}
}
Darüber hinaus wird tatsächlich "drainTo" mit einem Argument verwendet:
LinkedBlockingQueue.java
return drainTo(c, Integer.MAX_VALUE);
Und da nur dieselbe Methode aufgerufen wird, die überladen ist, gibt es kein Problem, wenn Sie dies überprüfen.
takeLock Ein Sperrobjekt zum Sperren des ** Abrufs ** von Daten.
putLock Obwohl es in der obigen Quelle nicht angezeigt wird, ist es ein Sperrobjekt zum Sperren des ** Hinzufügens ** von Daten.
count Ein Feld vom Typ "AtomicInteger". Jedes Mal, wenn ich die Daten ändere, scheint es, dass ich sie in der Klasse manuell ändere. (Es scheint, dass es nicht nur "Queue.size" zurückgibt)
Wir werden nur die notwendigen Teile in der Reihenfolge von oben betrachten.
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
Erwerben Sie die Erfassungssperre, bevor Sie mit der Datenerfassung beginnen.
Benötigen Sie ein zusätzliches Schloss? * Ich dachte, aber es wird aufgrund der folgenden Verarbeitung nicht mehr benötigt.
Holen Sie sich die Nummer
int n = Math.min(maxElements, count.get());
Bevor Sie mit der Datenerfassung beginnen, ** entscheiden Sie, wie viele Elemente von Anfang an erfasst werden sollen **. Auf diese Weise können Sie ** die während des DrainTo-Prozesses ** hinzugefügten Daten ignorieren.
Es scheint, dass es gesagt werden kann.
persönlich,
** Wenn Sie alle Daten auf einmal erhalten möchten, sollten Sie die Ergänzungen in der Zwischenzeit sperren! ** ** **
Ich werde denken.
Ich fragte mich, ob es einen Ansatz gab, "zuerst die Anzahl der Daten zu bestimmen". Es war eine sehr gute Studie.
Recommended Posts