Wie man ein Java-Vorstellungsgespräch besteht: Top-Fragen für Fortgeschrittene
Ein Vorstellungsgespräch für eine Position als Java-Entwickler auf fortgeschrittenem Niveau (Middle/Senior) ist nicht nur eine Überprüfung der Syntax. Interviewer möchten ein tiefes Verständnis der internen Funktionsweise der JVM, von Multithreading, der Algorithmen des Garbage Collectors und der Nuancen der Standardbibliothek sehen. In diesem Artikel analysieren wir die häufigsten und schwierigsten Fragen, die Ihnen helfen, Ihr technisches Interview souverän zu bestehen.
1. Multithreading und Synchronisation: von volatile bis Lock
Ein fortgeschrittenes Java-Vorstellungsgespräch beginnt fast immer mit Fragen zum Multithreading. Sie müssen nicht nur das Schlüsselwort synchronized kennen, sondern auch verstehen, wie volatile, AtomicInteger, ReentrantLock funktionieren und was happens-before bedeutet.
Frage: Was ist der Unterschied zwischen synchronized und ReentrantLock?
Der Hauptunterschied ist die Flexibilität. synchronized ist eine Sperre auf der Ebene des Objekt-Monitors. ReentrantLock bietet erweiterte Funktionen: die Möglichkeit, den Thread-Wartevorgang zu unterbrechen (lockInterruptibly()), den Versuch einer Sperre ohne Blockierung (tryLock()) sowie die Unterstützung mehrerer Bedingungen (Condition).
// Beispiel für die Verwendung von ReentrantLock mit Conditionimport java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.Condition;
public class BlockingQueueExample { private final ReentrantLock lock = new ReentrantLock(); private final Condition notFull = lock.newCondition(); private final Condition notEmpty = lock.newCondition(); private final Object[] items = new Object[10]; private int putIndex, takeIndex, count;
public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) { notFull.await(); // warten, bis Platz frei wird } items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); // signalisieren, dass ein Element vorhanden ist } finally { lock.unlock(); } }
public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) { notEmpty.await(); // warten, bis ein Element vorhanden ist } Object x = items[takeIndex]; if (++takeIndex == items.length) takeIndex = 0; count--; notFull.signal(); // signalisieren, dass Platz frei geworden ist return x; } finally { lock.unlock(); } }}Frage: Wie funktioniert das Schlüsselwort volatile?
volatile garantiert, dass das Lesen und Schreiben einer Variablen direkt aus dem Hauptspeicher (main memory) erfolgt, unter Umgehung des Prozessor-Caches. Dies gewährleistet die Sichtbarkeit von Änderungen für alle Threads, garantiert jedoch nicht die Atomarität (z. B. erfordert die Inkrementierung count++ weiterhin eine Synchronisation).
Denken Sie auch an happens-before: Das Schreiben in eine volatile-Variable erfolgt vor jedem nachfolgenden Lesen derselben Variable aus einem anderen Thread.
2. Java Memory Model (JMM) und Garbage Collector
Das Verständnis der Speicherverwaltung der JVM ist eine zwingende Voraussetzung für einen Senior-Entwickler. Interviewer fragen häufig nach den verschiedenen Generationen (Young/Old Generation), den Arten von Garbage Collectors und der JVM-Konfiguration.
Frage: Welche Arten von Garbage Collector gibt es in Java 17?
Modernes Java (17+) unterstützt mehrere GCs:
- G1GC (Garbage First) — Standard-GC. Teilt den Heap in Regionen auf und sammelt Müll in den Regionen mit der größten Anzahl toter Objekte.
- ZGC (Z Garbage