Różnica między oczekiwaniem a uśpieniem w Javie

1. Przegląd

W tym krótkim artykule przyjrzymy się standardowym metodom sleep () i wait () w podstawowej Javie oraz zrozumiemy różnice i podobieństwa między nimi.

2. Ogólne różnice między oczekiwaniem a snem

Mówiąc najprościej, wait () jest metodą instancji używaną do synchronizacji wątków.

Można go wywołać na dowolnym obiekcie, ponieważ jest zdefiniowany bezpośrednio w java.lang.Object, ale można go wywołać tylko z zsynchronizowanego bloku . Zwalnia blokadę obiektu, dzięki czemu kolejna nić może wskoczyć i zablokować się.

Z drugiej strony Thread.sleep () jest metodą statyczną, którą można wywołać z dowolnego kontekstu. Thread.sleep () wstrzymuje bieżący wątek i nie zwalnia żadnych blokad.

Oto bardzo uproszczone wstępne spojrzenie na te dwa podstawowe interfejsy API w działaniu:

private static Object LOCK = new Object(); private static void sleepWaitExamples() throws InterruptedException { Thread.sleep(1000); System.out.println( "Thread '" + Thread.currentThread().getName() + "' is woken after sleeping for 1 second"); synchronized (LOCK) { LOCK.wait(1000); System.out.println("Object '" + LOCK + "' is woken after" + " waiting for 1 second"); } } 

Uruchomienie tego przykładu da następujący wynik:

Wątek „main” budzi się po uśpieniu przez 1 sekundę

Obiekt „[email chroniony]” jest budzony po odczekaniu 1 sekundy

3. Budzenie Poczekaj i śpij

Kiedy używamy metody sleep () , wątek jest uruchamiany po określonym czasie, chyba że zostanie przerwany.

W przypadku wait () proces wybudzania jest nieco bardziej skomplikowany. Możemy obudzić wątek, wywołując metodę notify () lub notifyAll () na monitorze, na który oczekuje.

Jeśli chcesz obudzić wszystkie wątki, które są w stanie oczekiwania, użyj notifyAll () zamiast notify () . Podobnie jak w przypadku samej metody wait () , notify () i notifyAll () muszą być wywoływane z synchronizowanego kontekstu.

Na przykład, oto jak możesz czekać :

synchronized (b) { while (b.sum == 0) { System.out.println("Waiting for ThreadB to complete..."); b.wait(); } System.out.println("ThreadB has completed. " + "Sum from that thread is: " + b.sum); }

A następnie, oto jak inny wątek może obudzić oczekujący wątek - wywołując notify () na monitorze :

int sum; @Override public void run() { synchronized (this) { int i = 0; while (i < 100000) { sum += i; i++; } notify(); } }

Uruchomienie tego przykładu da następujący wynik:

Czekam na zakończenie ThreadB…

ThreadB został zakończony. Suma z tego wątku to: 704982704

4. Wniosek

To jest krótkie wprowadzenie do semantyki oczekiwania i snu w Javie.

Ogólnie rzecz biorąc, powinniśmy używać sleep () do kontrolowania czasu wykonania jednego wątku i wait () do synchronizacji wielowątkowej. Oczywiście jest o wiele więcej do zbadania - po dobrym zrozumieniu podstaw.

Jak zawsze, możesz zapoznać się z przykładami podanymi w tym artykule w witrynie GitHub.