Java-Quellcode-Analyse und Interview-Fragen-Interview-Fragen im Quellcode

Diese Reihe von verwandten Blog, Mu Klasse Referenzspalte Java - Quellcode und Systemhersteller Interviewer kurz und bündig Zhenti
unterhalb dieser Spalte ist GitHub - Adresse:
Quelle aufgelöst: https://github.com/luanqiu/java8
Artikel Demo: https: // GitHub. com / luanqiu / java8_demo
Klassenkameraden können es bei Bedarf ansehen)

Java-Quellcode-Analyse und Interview-Fragen-Interview-Fragen im Quellcode

Einleitende Satz
Warteschlangen stellen Fragen in Bezug auf den Quellcode, der allgemeine Eingang von der Interviewer des Thread - Pool sperrt usw. Als eine Frage des Wissens, langsam und bat um Warteschlange, weil die Sperre, der Thread - Pool wir nicht gelernt haben, so gerade auf das Thema dieses Kapitel ging Beginnen wir mit der Warteschlange und sehen, welche Interviewfragen sich in der Warteschlange befinden (es gibt viele Arten von Warteschlangen. Wenn Sie in diesem Artikel über die allgemeinen Merkmale der Warteschlange sprechen, sprechen sie über die allgemeinen Merkmale der meisten Warteschlangen. Anleitung).

1 Interviewfragen

1.1 Sprechen Sie über Ihr Verständnis von Warteschlangen, den Unterschied zwischen Warteschlangen und Sammlungen.
Antwort : Verständnis der Warteschlange:

  1. Zuallererst ist die Warteschlange selbst ein Container, und die unterste Ebene hat auch unterschiedliche Datenstrukturen. Beispielsweise ist LinkedBlockingQueue eine verknüpfte Listenstruktur im unteren Bereich, sodass die First-In-First-Out-Reihenfolge beibehalten werden kann. Beispielsweise kann die unterste Ebene von DelayQueue eine Warteschlange oder ein Stapel sein, sodass garantiert wird, dass sie First-In, First-Out oder ist Die Reihenfolge von First-In, First-Out usw. ist der zugrunde liegenden Datenstruktur unterschiedlich, was auch zu einer unterschiedlichen Operationsimplementierung führt.
  2. Einige Warteschlangen (z. B. LinkedBlockingQueue) bieten eine temporäre Speicherfunktion. Wir können Daten in die Warteschlange stellen und Daten aus der Warteschlange abrufen. Beide können gleichzeitig ausgeführt werden.
  3. Die Warteschlange entkoppelt die Partei, die Daten produziert, von der Partei, die Daten konsumiert. Der Produzent steuert nur die Produktion und der Konsument konsumiert nur. Es besteht keine notwendige Verbindung zwischen beiden. Die Warteschlange ist wie ein Datenkanal zwischen dem Produzenten und dem Konsumenten, z. B. LinkedBlockingQueue ;;
  4. Die Warteschlange kann auch Verbraucher und Produzenten verwalten. Wenn beispielsweise die Warteschlange voll ist und einige Produzenten noch Daten liefern, kann die Warteschlange den Produzenten blockieren und dessen Lieferung verhindern. Wenn die Person kommt, um die Daten abzurufen, kann die Warteschlange den Consumer Hodler am Leben lassen. Wenn Daten vorhanden sind, wecken Sie den Consumer auf und lassen Sie den Consumer die Daten zurückgeben, z. B. ArrayBlockingQueue.
  5. Die Warteschlange bietet auch eine Blockierungsfunktion. Wenn beispielsweise Daten aus der Warteschlange abgerufen werden, sich jedoch keine Daten in der Warteschlange befinden, wird der Thread blockiert, bis in der Warteschlange Daten zur Rückgabe verfügbar sind.

Der Unterschied zwischen Warteschlange und Sammlung:

  1. Ähnlich wie Sammlungen bieten Warteschlangen (einige Ausnahmen) und Sammlungen Datenspeicherfunktionen. Die zugrunde liegende Speicherdatenstruktur ist etwas ähnlich. Beispielsweise verwenden LinkedBlockingQueue und LinkedHashMap beide verknüpfte Listen und ArrayBlockingQueue und ArrayList beide. Ist ein Array.
  2. Der Unterschied zur Kollektion:
    • Die zugrunde liegende Speicherstruktur einiger Warteschlangen und einiger Sammlungen ist sehr ähnlich, aber um unterschiedliche Aufgaben zu erfüllen, unterscheiden sich die von beiden bereitgestellten APIs und ihre zugrunde liegenden Vorgänge.

    • Die Warteschlange bietet eine Blockierungsfunktion, die eine einfache Verwaltung von Verbrauchern und Produzenten ermöglicht. Wenn die Warteschlange leer ist, wird der Verbraucher blockiert. Nachdem andere Threads den Put-Vorgang ausgeführt haben, wird der blockierte Verbraucher aktiviert, damit der Verbraucher die Daten konsumieren kann. Auch wenn die Warteschlange voll ist.

    • Die Warteschlange entkoppelt den Produzenten und den Konsumenten und ist wie eine Pipeline zwischen dem Produzenten und dem Konsumenten. Der Produzent wirft sie nur ein und der Konsument konsumiert nur kontinuierlich. Die beiden kümmern sich nicht umeinander.

1.2 Welche Warteschlangen haben die Funktion zu blockieren und wie werden sie blockiert?
Antwort : Die Warteschlange bietet hauptsächlich zwei Blockierungsfunktionen:

  1. LinkedBlockingQueue und ArrayBlockingQueue sind zwei Arten von Blockierungswarteschlangen. Die Kapazität der ersteren ist der Maximalwert von Integer, und die Größe der letzteren ist festgelegt. Beide Blockierungswarteschlangen können die Kapazität angeben. Wenn die Warteschlange voll ist und Thread-Put-Daten vorhanden sind, wird der Thread Blockiert, bis andere Threads Daten verbrauchen, wird der blockierte Thread aktiviert und weiter gesetzt. Wenn die Warteschlange leer ist und ein Thread Daten aufnehmen soll, wird der Thread blockiert, bis die Warteschlange nicht leer ist, und wird fortgesetzt.
  2. SynchronousQueue Synchrone Warteschlange, wenn der Thread gesetzt wird, muss der entsprechende Thread die Daten verbrauchen, der Put-Thread kann zurückgeben, wenn der Thread nimmt, muss der entsprechende Thread Daten setzen, der Take kann zurückkehren, andernfalls kann das Blockieren beispielsweise Thread A Daten A1 in die Warteschlange stellen. Zu diesem Zeitpunkt gibt es keinen Verbraucher. Thread A kann nicht zurückkehren und wird blockiert. Thread A kann nicht zurückkehren, bis ein Thread Daten A1 verbraucht.

1.3 Wie blockiert die zugrunde liegende Ebene?
Antwort : Die Warteschlange selbst implementiert die Blockierungsfunktion nicht, verwendet jedoch den Wait-and-Wake-Mechanismus von Condition. Die zugrunde liegende Implementierung der Blockierung besteht darin, den Status des Threads in den Ruhezustand zu ändern, wie im Abschnitt "Sperren" erläutert wird.

1.4 Was ist der Unterschied zwischen LinkedBlockingQueue und ArrayBlockingQueue?
Antwort : Der gleiche Punkt:
Der Blockierungsmechanismus der beiden ist ungefähr der gleiche. Wenn beispielsweise die Warteschlange voll und leer ist, wird der Thread blockiert.

Unterschiede:

  1. Die unterste Ebene von LinkedBlockingQueue ist eine verknüpfte Listenstruktur, und die Kapazität ist standardmäßig der Maximalwert von Interge. Die unterste Ebene von ArrayBlockingQueue ist ein Array, und die Kapazität muss während der Initialisierung angegeben werden.
  2. Die zugrunde liegende Struktur der beiden ist unterschiedlich, daher ist auch die zugrunde liegende Implementierung von take, put und remove unterschiedlich.

1.5 Ist es sicher, Daten in die Warteschlange zu stellen? Warum?
A : Es ist threadsicher. Vor dem Put wird die Warteschlange automatisch gesperrt. Nach Abschluss des Put wird die Sperre automatisch aufgehoben, um sicherzustellen, dass nur ein Thread gleichzeitig mit den Warteschlangendaten arbeiten kann. Nehmen Sie als Beispiel LinkedBlockingQueue. Fügen Sie eine Put-Sperre hinzu und arbeiten Sie nur am Ende des Teams. Beim Take wird eine Take-Sperre hinzugefügt und nur am Kopf des Teams. Beim Entfernen werden sowohl Put- als auch Take-Sperren hinzugefügt, sodass verschiedene Vorgänge threadsicher sind. Wir können es mit Vertrauen in unsere Arbeit verwenden.

1.6 Wird es beim Aufnehmen gesperrt? Da sowohl put als auch take gesperrt sind, kann nur eine der Methoden gleichzeitig ausgeführt werden.
Antwort :

  1. Ja, es wird auch beim Aufnehmen gesperrt. Wenn beispielsweise LinkedBlockingQueue die take-Methode ausführt, werden die aktuellen Daten während des Aufnehmens gelöscht, wodurch die Datenstruktur der verknüpften Liste geändert wird. Daher muss sie gesperrt werden, um die Thread-Sicherheit zu gewährleisten.
  2. Dies hängt von der jeweiligen Situation ab. Bei LinkedBlockingQueue werden Put und Take der Warteschlange gesperrt, die Sperren der beiden sind jedoch unterschiedlich, sodass sich die beiden nicht gegenseitig beeinflussen und gleichzeitig ausgeführt werden können. Für ArrayBlockingQueue setzen und setzen take ist dieselbe Sperre, sodass jeweils nur eine Methode ausgeführt werden kann.

1.7 Welche Gefahren birgt die häufige Verwendung der Put & Take-Methoden der Warteschlange bei der Arbeit und wie können sie vermieden werden?
Antwort : Wenn die Warteschlange voll ist, wird die Verwendung der put-Methode blockiert, bis die Warteschlange nicht mehr voll ist.
Wenn die Warteschlange leer ist, wird die Verwendung der Methode take blockiert, bis die Warteschlange Daten enthält.

Beide Methoden sind unendlich (für immer, kein Timeout bedeutet Blockierungsmethode). Es ist einfach, alle Threads zu blockieren. Wenn der Flow groß ist, stehen dem Computer keine Threads zur Verfügung. Daher wird empfohlen, die Angebots- und Abfragemethoden zu verwenden, wenn der Flow groß ist Anstelle der beiden müssen wir nur die Timeout-Blockierungszeit festlegen. Wenn die beiden Methoden keine Daten außerhalb der Timeout-Zeit abrufen, kehren sie zum Standardwert zurück (als Beispiel LinkedBlockingQueue), damit nicht viel Verkehr entsteht Threads sind blockiert.

Dies ist auch einer der Gründe, warum Produktionsunfälle häufig auftreten. Der Versuch, die Put- und Take-Methoden zu verwenden, kann im üblichen Selbsttest nicht gefunden werden. Schüler, die mit dem Quellcode nicht vertraut sind, werden nicht erkennen, dass es Probleme geben wird. Wenn Online-Verkehr hereinkommt Es ist wahrscheinlich, dass dies fehlschlägt, daher müssen wir normalerweise vorsichtig sein, wenn wir Warteschlangen in unserer Arbeit verwenden.

1.8 Gibt es nach dem Einfügen von Daten in die Warteschlange eine Möglichkeit, die Warteschlange nach einer Weile ausführen zu lassen?
Antwort : Ja, DelayQueue bietet diesen Mechanismus, der so eingestellt werden kann, dass er nach einer bestimmten Zeit ausgeführt wird. Der einzige Nachteil dieser Warteschlange besteht darin, dass die Daten im Speicher gespeichert werden. Beim Neustart und Ausschalten gehen die Daten leicht verloren, sodass sie geplant werden. Wir werden die Zeit nicht für eine lange Zeit einstellen, normalerweise innerhalb weniger Sekunden. Wenn die geplante Zeit für eine lange Zeit eingestellt werden muss, können Sie eine Übernahme in Betracht ziehen 延迟队列中间件(diese Art von Middleware behält die Daten bei, ohne Angst vor einem Stromausfall zu haben), um dies zu erreichen.

1.9 Hat DelayQueue Anforderungen an Elemente? Kann ich String in die Warteschlange stellen?
Antwort : DelayQueue erfordert, dass die Elemente die Delayed-Schnittstelle implementieren, und Delayed selbst implementiert die Comparable-Schnittstelle. Die Rolle der Delayed-Schnittstelle besteht darin, zu definieren, wie lange das Zeitlimit überschritten wird, und den Timeout-Zeitraum für Benutzer anzupassen. Die Comparable-Schnittstelle wird hauptsächlich für das Inter-Element verwendet Die Sortierung der Timeout-Zeit, die Kombination der beiden, kann dazu führen, dass die Elemente, die früher ablaufen, vorne schneller ablaufen.

Daher ist es nicht akzeptabel, String in DelayQueue einzufügen, und die Kompilierung wird nicht bestanden. Wenn die DelayQueue-Klasse definiert ist, wird sie durch einen generischen Typ definiert. Der generische Typ muss eine Unterklasse der Delayed-Schnittstelle sein.

1.10 Wie lässt DelayQueue Elemente, die bald ablaufen, zuerst ausgeführt werden?
Antwort : Die Elemente in DelayQueue implementieren sowohl verzögerte als auch vergleichbare Schnittstellen, die die Sortiermethode CompareTo zum Sortieren verwenden. Mit dieser Funktion können wir die Differenz zwischen der Ablaufzeit und der aktuellen Zeit in der compareTo-Methode implementieren. Je früher die Elemente abgelaufen sind Je kleiner die berechnete Differenz ist, desto früher wird sie ausgeführt.

1.11 Wie überprüfe ich die Größe von SynchronousQueue?
Antwort : Diese Frage ist eine Falle. Bei dieser Frage wird zuerst die SynchronousQueue so eingestellt, dass die Größe überprüft wird. Tatsächlich hat SynchronousQueue selbst keine Kapazität, sodass die Größe der Kapazität nicht überprüft werden kann. Die interne Größenmethode besteht darin, zum Tod zurückzukehren. 0.

1.12 Am Ende von SynchronousQueue befinden sich mehrere Datenstrukturen. Was ist der Unterschied zwischen den beiden?
Antwort : In der untersten Ebene gibt es zwei Arten von Datenstrukturen, nämlich Warteschlange und Stapel.

Der Unterschied zwischen den beiden: Die
Warteschlange behält die First-In-First-Out-Reihenfolge bei, sodass die am weitesten fortgeschrittenen Elemente, die in die Warteschlange gestellt werden sollen, zuerst verbraucht werden, was wir als fair bezeichnen. Der Stapel ist die First-In-, First-Out-Reihenfolge und die Daten im Stapel Es kann am Ende konsumiert werden, was wir als unfair bezeichnen.
Die Datenstruktur der beiden ist unterschiedlich, was zu Unterschieden bei den Methoden take und put führt. Weitere Informationen finden Sie im Kapitel "SynchronousQueue Source Code Analysis".

1.13 Unter der Annahme, dass die Unterseite von SynchronousQueue einen Stapel verwendet, wird Thread 1 durch die Take-Operation blockiert, und dann führt Thread 2 die Put-Operation aus. Wie übergibt Thread 2 die Put-Daten, die zu diesem Zeitpunkt genommen werden sollen?
Antwort : Dies ist eine gute Frage und auch das Kernproblem beim Verständnis von SynchronousQueue.

Zunächst wird Thread 1 blockiert. Zu diesem Zeitpunkt ist der Stapelkopf Thread 1. Zu diesem Zeitpunkt führt Thread 2 eine Put-Operation aus, und die Put-Daten werden dem Übereinstimmungsattribut des Stapelkopfs zugewiesen, und Thread 1 wird aufgeweckt. Nachdem Thread 1 aufgeweckt wurde, wird er abgerufen Mit dem Match-Attribut im Stack-Header können Sie die Put-Daten abrufen.

Genau genommen ist es nicht so, dass die Put-Operation die Daten direkt in den Take überträgt, sondern dass die Put-Operation die Daten des Stapel-Headers ändert, so dass der Take die Daten direkt aus dem Stack-Header abrufen kann und der Stack-Header das Kommunikationsmedium zwischen den Take- und Put-Operationen ist .

1.14 Wenn Sie eine Warteschlange mit fester Größe verwenden möchten, stehen verschiedene Arten von Warteschlangen zur Auswahl. Was ist der Unterschied?
Antwort : LinkedBlockingQueue und ArrayBlockingQueue können verwendet werden.

Ersteres ist eine verknüpfte Liste, und letzteres ist ein Array. Wenn die verknüpfte Liste hinzugefügt wird, muss die Position des Index beim Hinzufügen des Arrays berücksichtigt werden, solange die Zuordnung zwischen den neuen Daten und den Enddaten hergestellt wird (takeIndex und putIndex werden separat aufgezeichnet Nehmen Sie den Index der Daten und setzen Sie den Index der Daten. Wenn er bis zur letzten Position des Arrays ansteigt, wird er beim nächsten Mal erneut hinzugefügt.

1.15 Kann ArrayBlockingQueue dynamisch erweitert werden? Was tun, wenn die letzte Position des Arrays verwendet wird?
Antwort : Nein, obwohl die unterste Ebene von ArrayBlockingQueue ein Array ist, kann sie nicht dynamisch erweitert werden.

Angenommen, die Put-Operation verwendet die letzte Position des Arrays, muss der nächste Put von der Position des Arrays 0 aus neu gestartet werden.

Angenommen, die Take-Operation verwendet die letzte Position des Arrays, beginnt die nächste Take wieder an der Position des Arrays 0.

1.16 Wie nimmt ArrayBlockingQueue die Indexposition und findet sie? Wird es mit dem Hash-Algorithmus berechnet?
Antwort : ArrayBlockingQueue verfügt über zwei Attribute, takeIndex und putIndex, die jeweils die Position des nächsten Take und Put angeben. Jedes Mal, wenn take und put abgeschlossen werden, werden sie um eins erhöht. Obwohl die unterste Ebene ein Array ist, unterscheidet sie sich von HashMap und wird nicht übergeben. Berechnet durch den Hash-Algorithmus.

2 Zusammenfassung

Warteschlangen bilden die Grundlage für komplexe APIs wie Sperren und Thread-Pools. Viele Interviewer fragen Sie nach dem Wissen über Warteschlangen, wenn Sie diese APIs fragen. Wenn Sie nicht gut antworten, glaubt der Interviewer möglicherweise, dass Sie nur Sperren und Thread-Pools verwendet haben. Die zugrunde liegenden Prinzipien und die Implementierung sind jedoch nicht vollständig verstanden, sodass die Warteschlange immer noch sehr wichtig ist, der Quellcode der Warteschlange jedoch komplizierter ist. Es wird empfohlen, die Debug-Methode zu verwenden, um den Quellcode zu verstehen.

Veröffentlicht 40 Originalarbeiten · erntete Lob 1 · Ansichten 4982

Ich denke du magst

Origin blog.csdn.net/aha_jasper/article/details/105525836
Empfohlen
Rangfolge