JavaRush /Java-Blog /Random-DE /Übersetzung: Top 50 Interviewfragen nach Thread. Teil 2.
KapChook
Level 19
Volga

Übersetzung: Top 50 Interviewfragen nach Thread. Teil 2.

Veröffentlicht in der Gruppe Random-DE
Der zweite Teil der Übersetzung des Originalartikels „ Top 50 Java Thread Interview Questions Answers for Freshers, Experienced Programmers“. Erster Teil.
  1. Wie überprüfe ich, ob ein Thread eine Sperre hält?

  2. Ich hatte keine Ahnung, dass man überprüfen kann, ob ein Thread gerade gesperrt ist, bis ich in einem Telefoninterview auf diese Frage stieß. java.lang.Thread verfügt über eine holdLock()-Methode, die genau dann true zurückgibt, wenn der aktuelle Thread den Monitor für ein bestimmtes Objekt hält.
  3. Wie bekomme ich einen Thread-Dump?

  4. Mit einem Thread-Dump können Sie herausfinden, was ein Thread gerade tut. Abhängig vom Betriebssystem gibt es mehrere Möglichkeiten, einen Thread-Dump zu erhalten. Unter Windows können Sie die Kombination Strg + Pause verwenden, unter Linux können Sie den Befehl kill -3 verwenden. Sie können auch das Dienstprogramm jstack verwenden; es arbeitet mit der Prozess-ID, die Sie mit einem anderen Dienstprogramm jps ermitteln können.
  5. Welcher JVM-Parameter wird verwendet, um die Stapelgröße des Threads zu steuern?

  6. Dies ist einer der einfachen Parameter -Xss, mit denen die Größe des Stapels eines Threads in Java gesteuert wird.
  7. Unterschiede zwischen synchronisiert und ReentrantLock?

  8. Es gab Zeiten, in denen die einzige Möglichkeit, gegenseitigen Ausschluss zu erreichen, das Schlüsselwort synchronisiert war, aber es hat mehrere Nachteile, wie z. B. die Möglichkeit, die Sperre nicht über eine Methode oder einen Codeblock hinaus auszudehnen usw. Java 5 löst dieses Problem, indem es über die Lock-Schnittstelle eine detailliertere Kontrolle bietet. ReentrantLock ist eine gängige Lock-Implementierung, die einem Lock das gleiche grundlegende Verhalten und die gleiche Semantik wie ein impliziter Monitor bietet, erreicht durch synchronisierte Methoden, jedoch mit erweiterten Funktionen.
  9. Gegeben 3 Threads T1, T2 und T3? Wie implementiert man die Reihenfolge T1, T2, T3?

  10. Konsistenz kann auf viele Arten erreicht werden, aber Sie können einfach die Methode „join()“ verwenden, um einen Thread zu starten, wenn die Ausführung eines anderen Threads abgeschlossen ist. Um die angegebene Sequenz zu implementieren, müssen Sie zuerst den letzten Thread starten und dann die Methode join() in umgekehrter Reihenfolge aufrufen, d. h. T3 ruft T2.join auf und T2 ruft T1.join auf, sodass T1 zuerst und T3 zuletzt beendet wird .
  11. Was bewirkt die Ertragsmethode?

  12. Die Yield-Methode ist eine Möglichkeit, einen Thread aufzufordern, CPU abzugeben, damit ein anderer Thread ausgeführt werden kann. Dies ist eine statische Methode und sie stellt nur sicher, dass der aktuelle Thread den Prozessor aufgibt, entscheidet jedoch nicht, zu welchem ​​Thread die Ausführung erfolgen soll.
  13. Was ist der Parallelitätsgrad von ConcurrentHashMap?

  14. ConcurrentHashMap erreicht seine Skalierbarkeit und Thread-Sicherheit durch die Aufteilung der eigentlichen Karte in Abschnitte. Diese Trennung wird durch die Verwendung einer Parallelitätsebene erreicht. Dies ist ein optionaler Parameter für den ConcurrentHashMap-Konstruktor und sein Standardwert ist 16.
  15. Was ist Semaphor?

  16. Semaphore ist eine neue Art von Synchronisierer. Dies ist ein Semaphor mit Zähler. Konzeptionell steuert ein Semaphor eine Reihe von Berechtigungen. Jeder acquire() blockiert, falls erforderlich, bevor die Berechtigung verfügbar ist, und erwirbt sie dann. Jedes release() fügt eine Berechtigung hinzu und gibt möglicherweise den blockierenden Acquirer frei. Dabei werden jedoch keine tatsächlichen Berechtigungsobjekte verwendet; Semaphore speichert einfach die Anzahl der verfügbaren und handelt entsprechend. Semaphor wird verwendet, um teure Ressourcen zu schützen, die in begrenzten Mengen verfügbar sind, beispielsweise eine Verbindung zu einer gepoolten Datenbank.
  17. Was passiert, wenn die Thread-Pool-Warteschlange bereits voll ist und Sie eine Aufgabe übermitteln?

  18. Wenn die Thread-Pool-Warteschlange voll ist, wird die übermittelte Aufgabe „abgelehnt“. Die Methode „submit()“ von ThreadPoolExecutor löst eine RejectedExecutionException aus, woraufhin der RejectedExecutionHandler aufgerufen wird.
  19. Unterschiede zwischen den Methoden „submit()“ und „execute()“ in einem Thread-Pool?

  20. Bei beiden Methoden handelt es sich um Möglichkeiten, eine Aufgabe an einen Thread-Pool zu senden, es gibt jedoch einen kleinen Unterschied zwischen ihnen. Execute (ausführbarer Befehl) wird in der Executor-Schnittstelle definiert und führt die gegebene Aufgabe in der Zukunft aus, gibt aber, was noch wichtiger ist, nichts zurück. Andererseits ist subscribe() eine überladene Methode, sie kann ausführbare und aufrufbare Aufgaben akzeptieren und ein Future-Objekt zurückgeben, das zum Abbrechen der Ausführung und/oder zum Warten auf das Ergebnis einer Berechnung verwendet werden kann. Diese Methode ist in der ExecutorService-Schnittstelle definiert, die von der Executor-Schnittstelle erbt, und jede Thread-Pool-Klasse, wie ThreadPoolExecutor oder ScheduledThreadPoolExecutor, erbt diese Methoden.
  21. Was ist eine Blockierungsmethode?

  22. Eine Blockierungsmethode ist eine Methode, die blockiert, bis die Aufgabe abgeschlossen ist. Beispielsweise blockiert die ServerSocket-Accept()-Methode, während sie darauf wartet, dass der Client eine Verbindung herstellt. Blockieren bedeutet hier, dass die Kontrolle nicht an die aufrufende Methode zurückgegeben wird, bis der Job abgeschlossen ist. Andererseits gibt es asynchrone oder nicht blockierende Methoden, die abgeschlossen werden, bevor die Aufgabe abgeschlossen ist.
  23. Ist Swing-Thread sicher?

  24. Einfach ausgedrückt: Nein, Swing ist nicht threadsicher, aber Sie müssen erklären, was Sie damit meinen, auch wenn der Interviewer nicht danach fragt. Wenn wir sagen, dass Swing nicht threadsicher ist, beziehen wir uns normalerweise auf die Tatsache, dass es sich um eine Komponente handelt, die nicht von mehreren Threads geändert werden kann. Alle Änderungen an GUI-Komponenten müssen im AWT-Thread vorgenommen werden, und Swing bietet synchrone und asynchrone Methoden zum Planen solcher Änderungen.
  25. Unterschiede zwischen invokeAndWait und invokeLater?

  26. Dies sind zwei Swing-API-Methoden, die es Entwicklern ermöglichen, GUI-Komponenten über Threads statt über den Event Manager-Thread zu aktualisieren. InvokeAndWait() aktualisiert synchron eine GUI-Komponente wie einen Fortschrittsbalken; jedes Mal, wenn ein Fortschritt erzielt wird, muss der Balken aktualisiert werden, um die Änderungen widerzuspiegeln. Wenn der Fortschritt in einem anderen Thread verfolgt wird, muss er invokeAndWait() aufrufen, um den Event Dispatcher-Thread zuzuweisen, diese Komponente zu aktualisieren. Und invokeLater() ist ein asynchroner Aufruf zum Aktualisieren von Komponenten.
  27. Welche Swing-API-Methoden sind threadsicher?

  28. Bei dieser Frage geht es erneut um Swing und Thread-Sicherheit. Obwohl Swing-Komponenten nicht Thread-sicher sind, gibt es Methoden, die sicher von mehreren Threads aufgerufen werden können. Ich weiß, dass repaint() und revalidate() threadsicher sind, aber es gibt auch andere Methoden für verschiedene Swing-Komponenten, wie etwa die setText()-Methoden von JTextComponent und die insert()- und append()-Methoden von JTextArea.
  29. Wie erstelle ich unveränderliche Objekte?

  30. Diese Frage scheint nichts mit Multithreading und Parallelität zu tun zu haben, aber sie hat es. Unveränderlichkeit trägt dazu bei, bereits komplexen parallelen Code zu vereinfachen. Ein unveränderliches Objekt ist für Entwickler sehr teuer, da es ohne Synchronisierung weitergegeben werden kann. Leider verfügt Java nicht über die Annotation @Immutable, die Ihr Objekt unveränderlich macht. Dafür müssen Entwickler hart arbeiten. Um ein unveränderliches Objekt zu erstellen, müssen Sie die Grundlagen befolgen: Initialisierung im Konstruktor, keine Setter, kein Referenzverlust, separate Kopien veränderlicher Objekte speichern.
  31. Was ist ReadWriteLock?

  32. Im Allgemeinen ist ReadWriteLock das Ergebnis einer Lock-Parsing-Technik zur Verbesserung der Leistung paralleler Anwendungen. Dies ist eine Schnittstelle, die in Java 5 hinzugefügt wurde. Sie arbeitet mit einem Paar verwandter Sperren, eine für Lesevorgänge und eine für Schreibvorgänge. Eine Lesersperre kann gleichzeitig von mehreren Lesethreads gehalten werden, bis keine Schreiber mehr vorhanden sind. Die Schreibsperre ist exklusiv. Wenn Sie möchten, können Sie eine Schnittstelle mit Ihrem Regelsatz implementieren oder ReentrantReadWriteLock verwenden, das maximal 65535 rekursive Schreibsperren und 65535 Lesesperren unterstützt.
  33. Was ist Busy Spin?

  34. Busy Spin ist eine Technik, mit der Programmierer einen Thread zwingen, unter einer bestimmten Bedingung zu warten. Im Gegensatz zu den herkömmlichen Methoden wait(), sleep() oder yield(), bei denen die Kontrolle über den Prozessor abgegeben wird, gibt diese Methode den Prozessor nicht ab, sondern führt einfach eine leere Schleife aus. Warum sollte jemand das tun? Um den Prozessor-Cache zu speichern. Auf Systemen mit mehreren Kernen ist es möglich, dass ein angehaltener Thread weiterhin auf einem anderen Kern ausgeführt wird, was einen Cache-Neuaufbau bedeutet. Um kostspielige Neuerstellungen zu vermeiden, zieht der Programmierer es vor, durch die Verwendung von Busy Spin kürzere Wartezeiten zu erzielen.
  35. Unterschiede zwischen flüchtigen und atomaren Variablen?

  36. Das ist eine recht interessante Frage, flüchtige und atomare Variablen sehen auf den ersten Blick sehr ähnlich aus, sind aber dennoch unterschiedlich. Eine flüchtige Variable bietet eine Vorher-Garantie dafür, dass ein Schreibvorgang vor jedem nachfolgenden Schreibvorgang erfolgt; sie garantiert keine Atomizität. Beispielsweise wird die Operation count++ nicht atomar, nur weil count als flüchtig deklariert ist. Andererseits stellt die AtomicInteger-Klasse eine atomare Methode bereit, um solche komplexen Operationen atomar auszuführen. getAndIncrement() ist beispielsweise ein atomarer Ersatz für den Inkrementierungsoperator und kann verwendet werden, um den aktuellen Wert atomar um eins zu erhöhen. Es gibt auch atomare Versionen für andere Datentypen.
  37. Was passiert, wenn ein Thread eine Ausnahme in einem synchronisierten Block auslöst?

  38. Dies ist eine weitere Trickfrage für normale Java-Programmierer. Unabhängig davon, wie Sie einen synchronisierten Block verlassen, entweder normalerweise durch Beenden der Ausführung oder plötzlich durch Auslösen einer Ausnahme, gibt der Thread die erworbene Sperre auf, wenn er in den synchronisierten Block eintritt. Dies ist einer der Gründe, warum ich einen synchronisierten Sperrblock einer Schnittstelle vorziehe, die beim Aufheben der Sperre besondere Sorgfalt erfordert, was normalerweise durch das Aufheben der Sperre in einem „finally“-Block erreicht wird.
  39. Was ist Singletons doppelt geprüfte Verriegelung?

  40. Dies ist eine der beliebtesten Fragen in Vorstellungsgesprächen, und trotz ihrer Beliebtheit liegt die Wahrscheinlichkeit, dass ein Kandidat sie beantwortet, bei bestenfalls 50 %. In der Hälfte der Fälle scheitern sie daran, den Code zu schreiben, und in der anderen Hälfte daran, zu erklären, wie er in Java 1.5 kaputt gegangen und behoben wurde. Dies ist eine alte Methode zum Erstellen eines Thread-sicheren Singletons, die versucht, die Leistung zu optimieren, indem sie nur blockiert, wenn die Singleton-Instanz zum ersten Mal instanziiert wird. Aufgrund der Komplexität und der Tatsache, dass sie in JDK 1.4 fehlerhaft war, gefällt sie mir persönlich jedoch nicht Es. Auch wenn Sie diesen Ansatz nicht bevorzugen, ist es dennoch nützlich, ihn aus der Perspektive eines Vorstellungsgesprächs zu kennen.
  41. Wie erstelle ich einen threadsicheren Singleton?

  42. Diese Frage ergänzt die vorherige. Wenn Sie sagen, dass Ihnen doppelt geprüftes Sperren nicht gefällt, wird der Interviewer gezwungen sein, nach alternativen Möglichkeiten zum Erstellen eines threadsicheren Singleton zu fragen. Sie können die Funktionen zum Laden von Klassen und zur Initialisierung statischer Variablen nutzen, um Singleton zu instanziieren, oder Sie können den leistungsstarken Enum-Typ nutzen.
  43. Listen Sie 3 Bräuche auf, denen Sie bei der Parallelprogrammierung folgen?

  44. Das ist meine Lieblingsfrage, weil ich glaube, dass es beim Schreiben von parallelem Code bestimmte Regeln gibt, die befolgt werden müssen, was die Leistung, das Debuggen und den Support verbessert. Nachfolgend sind die drei besten Regeln aufgeführt, die meiner Meinung nach jeder Java-Programmierer befolgen sollte:
    • Geben Sie Ihren Threads immer aussagekräftige Namen
    • Einen Fehler zu finden oder eine Ausnahme im parallelen Code aufzuspüren, ist eine ziemlich schwierige Aufgabe. OrderProcessor, QuoteProcessor oder TradeProcessor ist viel besser als Thread-1. Thread-2 und Thread-3. Der Name sollte die vom Thread ausgeführte Aufgabe widerspiegeln. Alle wichtigen Frameworks und sogar JDK folgen dieser Regel.
    • Vermeiden Sie Blockierungen oder reduzieren Sie den Synchronisierungsbereich
    • Blockieren ist teuer und Kontextwechsel ist noch teurer. Vermeiden Sie Synchronisierung und Blockierung so weit wie möglich, um den kritischen Abschnitt auf das erforderliche Minimum zu reduzieren. Aus diesem Grund bevorzuge ich eine zeitgesteuerte Blockierung gegenüber einer zeitgesteuerten Methode, da Sie damit die absolute Kontrolle über das Ausmaß der Blockierung haben.
    • Wählen Sie zwischen Synchronisierern und Warten und Benachrichtigen Synchronisierer aus
    • Erstens vereinfachen Synchronisierer wie CountDownLatch, Semaphore, CyclicBarrier oder Exchanger die Codierung. Es ist sehr schwierig, einen komplexen Kontrollfluss mithilfe von Warten und Benachrichtigen zu implementieren. Zweitens werden diese Klassen von den Besten der Branche geschrieben und gepflegt und es besteht eine gute Chance, dass sie in zukünftigen JDK-Versionen optimiert oder durch besseren Code ersetzt werden. Durch die Verwendung hochwertiger Synchronisierungsdienstprogramme profitieren Sie automatisch von all diesen Vorteilen.
    • Wählen Sie zwischen „Concurrent Collection“ und „Synchronized Collection“ „Concurrent Collection“ aus
    • Dies ist eine weitere einfache Regel, die leicht zu befolgen und von den Vorteilen zu profitieren ist. Gleichzeitige Sammlungen sind skalierbarer als ihre synchronisierten Gegenstücke, daher ist es besser, sie beim Schreiben von parallelem Code zu verwenden. Wenn Sie also das nächste Mal eine Karte benötigen, denken Sie an ConcurrentHashMap, bevor Sie an Hashtable denken.
  45. Wie erzwinge ich den Start eines Threads?

  46. Dies ist eine Frage a la, wie man die Ausführung der Garbage Collection erzwingen kann. Kurz gesagt, Sie können natürlich auf keinen Fall eine Abfrage mit System.gc() durchführen, aber das garantiert nichts. Es gibt absolut keine Möglichkeit, den Start eines Threads in Java zu erzwingen. Dies wird vom Thread-Scheduler gesteuert und Java stellt keine API zur Steuerung bereit. Dieser Teil von Java ist immer noch zufällig.
  47. Was ist das Fork/Join-Framework?

  48. Das in JDK 7 eingeführte Fork/Join-Framework ist ein leistungsstarkes Dienstprogramm, das es dem Entwickler ermöglicht, die Vorteile mehrerer Prozessoren moderner Server zu nutzen. Es ist für Arbeiten konzipiert, die rekursiv in kleine Partikel zerlegt werden können. Ziel ist es, die gesamte verfügbare Rechenleistung zu nutzen, um die Leistung Ihrer Anwendung zu steigern. Ein wesentlicher Vorteil dieses Frameworks besteht darin, dass es einen Work-Stealing-Algorithmus verwendet (von Work – Work and Steal – to Steal). Worker-Threads, denen die Jobs ausgehen, können Jobs von anderen Threads stehlen, die noch beschäftigt sind.
  49. Was ist der Unterschied zwischen den Aufrufen von wait() und sleep()?

  50. Obwohl sowohl „Wait“ als auch „Sleep“ eine Art Pause in einer Java-Anwendung darstellen, handelt es sich um Geräte für unterschiedliche Anforderungen. Wait wird für die interne Thread-Kommunikation verwendet. Es gibt eine Sperre auf, wenn die Wartebedingung wahr ist, und wartet auf eine Benachrichtigung, wenn die Aktionen eines anderen Threads die Wartebedingung falsch machen. Andererseits gibt die Methode „sleep()“ einfach den Prozessor auf oder stoppt die Ausführung des aktuellen Threads für eine bestimmte Zeitspanne. Durch den Aufruf von sleep() wird die vom aktuellen Thread gehaltene Sperre nicht aufgehoben.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION