wait() vs sleep() in Java: Kampf der Titanen des Multithreadings
\n\nStellen Sie sich vor, Sie sind der Dirigent eines Orchesters. Sie haben Geiger (Threads), die harmonisch spielen müssen, aber manchmal müssen sie warten, bis andere ihren Part beendet haben. In Java gibt es zwei mächtige Werkzeuge, um solche Pausen zu verwalten: wait() und sleep(). Auf den ersten Blick ähneln sie sich – beide lassen einen Thread für eine Weile „einfrieren“. Aber in Wirklichkeit sind es völlig unterschiedliche Mechanismen, und sie zu verwechseln ist der sichere Weg zu einem Deadlock oder einer Race Condition.
Dieser Artikel ist Ihr Leitfaden durch den Dschungel des Multithreadings. Wir werden nicht nur die Unterschiede auflisten, sondern sie anhand lebendiger Beispiele analysieren, damit Sie sich für immer merken: sleep ist eine Pause, wait ist die Freigabe einer Ressource. Los geht's!
\n\nWas ist sleep()? (Thread.sleep)
\n\nDie Methode Thread.sleep(Millisekunden) ist der einfachste Weg, den aktuellen Thread für eine bestimmte Zeit „schlafen zu legen“. Der Thread ruht sich einfach aus, ohne Sperren auf Objekten freizugeben. Er ist wie eine faule Katze, die auf dem Sofa döst, aber weiterhin mit der Pfote ein Spielzeug festhält.
Wichtige Fakten über sleep():
- \n
- Es ist eine statische Methode der Klasse
Thread. \n - Der Thread gibt keine Monitore (Sperren) frei, die er hält. \n
- Nach Ablauf des Timers wechselt der Thread in den Zustand Runnable (bereit zur Ausführung). \n
- Kann eine
InterruptedExceptionauslösen. \n
Ein einfaches Beispiel:
\npublic class SleepExample {\n public static void main(String[] args) throws InterruptedException {\n System.out.println("Start: " + System.currentTimeMillis());\n Thread.sleep(2000); // schlafe 2 Sekunden\n System.out.println("Aufgewacht: " + System.currentTimeMillis());\n }\n}\n\nErgebnis: Zwischen den beiden Ausgaben liegen genau 2 Sekunden. Der Thread hat einfach gewartet, ohne etwas zu tun.
\n\nWas ist wait()? (Object.wait)
\n\nDie Methode wait() ist nicht nur eine Pause, sondern ein Mechanismus zur Kommunikation zwischen Threads. Sie ist in der Klasse Object definiert und kann nur innerhalb eines synchronisierten Blocks (synchronized) aufgerufen werden. Wenn ein Thread wait() aufruft, tut er Folgendes:
- \n
- Er gibt den Monitor des Objekts frei (gibt also die Sperre ab). \n
- Er wechselt in den Zustand WAITING oder TIMED_WAITING (falls ein Timeout angegeben ist). \n
- Er wartet, bis ein anderer Thread
notify()odernotifyAll()auf demselben Objekt aufruft. \n
Das ist, als ob Sie sagen würden: „Ich lege die Gabel hin und warte, bis mir der zweite Gang gebracht wird.“ Sie schlafen nicht nur – Sie machen den Platz am Tisch für einen anderen frei.
\n\nEin grundlegendes Beispiel:
\npublic class WaitNotifyExample {\n private static final Object lock = new Object();\n\n public static void main(String[] args) throws InterruptedException {\n Thread waiter = new Thread(() -> {\n synchronized (lock) {\n try {\n System.out.println("Kellner-Thread wartet...");\n lock.wait(); // gibt lock frei und wartet\n System.out.println("Kellner-Thread hat Benachrichtigung erhalten!");\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n }\n });\n\n Thread notifier = new Thread(() -> {\n synchronized (lock) {\n System.out.println("Koch-Thread kocht...");\n try {\n Thread.sleep(1000); // Kochvorgang simulieren\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n lock.notify(); // weckt den wartenden Thread\n System.out.println("Koch hat den Kellner benachrichtigt!");\n }\n });\n\n waite