2012-03-14 8 views
10

Mam pętlę główną w wątku, a jego część sprawdza, czy wartość boolean bezczynności jest prawdziwa. Jeśli tak, zadzwoni pod numer Thread.sleep(1) po każdej iteracji pętli. Czy jest to skuteczny sposób na zrobienie tego? Moim celem jest, aby wątek zużył minimalne użycie procesora, gdy jest bezczynny.Czy w Javie można używać Thread.sleep (1) do wątku bezczynności?

+0

Czy to nie potrwa, zanim system będzie ciągle wymieniał wątki w ten sposób? To wymaga mocy obliczeniowej, aby menedżer wątków wykonał swoje zadanie, a Ty prosisz o wykonanie tej pracy co milisekundę. – scriptocalypse

+0

Jedna rzecz, którą podejrzewałem, może się zdarzyć, ale nie byłem wtedy pewien. To brzmi jak 'wait' i' notifyAll' wykona zadanie dobrze. – AutoBotAM

Odpowiedz

8

Zamiast tego należy użyć Object.wait i upewnić się, że synchronizowano obiekt zawierający wartość logiczną. Jeśli nie dokonasz synchronizacji, a boolean nie jest volatile, nie masz żadnej bariery pamięci, więc nie ma gwarancji, że wątek odpytywania zobaczy zmianę na boolean.

Według javadoc:

Metoda ta powoduje bieżącego wątku (nazwać T), aby umieścić się w zestawie oczekiwania dla tego obiektu i do oddania wszelkie żądania synchronizacji tego obiektu. Temat T staje wyłączone dla celów planowania wątek i drzemie dopóki jeden z czterech rzeczy dzieje:

  • Jakiś inny wątek wywołuje metodę notify dla tego obiektu i nici T dzieje się dowolnie wybrany wątek, aby być budzony .
  • Inny wątek wywołuje metodę notifyAll dla tego obiektu.
  • Jakiś inny wątek przerywa wątek T.
  • ...

więc nitka będzie miała żadnego procesora podczas oczekiwania mają być notyfikowane.

Poniższy kod jest prostą flagą bezczynności z metodą waitUntilIdle, którą można wywołać metodą main i metodą setIdle, którą można wywołać innym wątkiem.

public class IdleFlag { 
    private boolean idle; 

    public void waitUntilIdle() throws InterruptedException { 
    synchronized (this) { 
     while (true) { 
     // If the flag is set, we're done. 
     if (this.idle) { break; } 
     // Go to sleep until another thread notifies us. 
     this.wait(); 
     } 
    } 
    } 

    public void setIdle() { 
    synchronized (this) { 
     this.idle = true; 
     // Causes all waiters to wake up. 
     this.notifyAll(); 
    } 
    } 
} 
+0

Chociaż to zadziała, jaki jest powód 'while (true)' poza synchronizacją? Po prostu zwolni blokadę i ponownie zacznie działać po odczekaniu (a następnie zwolnieniu). Zgodnie z określeniem 'while (true)' w synchronizacji, uzyskaj/zwolnij semantykę (tylko raz) za każdym razem, gdy oczekiwane jest powiadomienie (regularnie lub fałszywie). –

+1

Cóż, myślę, że moim celem jest, abyś mógł po prostu 'while' w synchronizacji, w której nie musiałbyś wydać dodatkowego wydania/zdobyć, robiąc to na zewnątrz. Masz rację, nie wyrządza żadnej szkody funkcjonalnej, a wpływ na wydajność jest prawdopodobnie znikomy. –

+0

@JohnVint, dobry punkt. Edytowane. –

1

zgadzam się z @Mike Samuela, jeszcze chciałbym zalecić użyć concurrent lock packages...

Kontynuuj paradygmatu Mike'a prostu wymienić swój zamek, który wprowadził w Javie 5

Dokładniej ty mogą korzystać z metod oczekujących na metody - te, które mają limity czasowe. W ten sposób możesz, na przykład, rejestrować wiadomość co jakiś czas - wiadomość, która pomoże ci zdebugować nieskończone oczekiwania. Możesz także chcieć wykonać logikę wycofywania, jeśli oczekiwanie na timeout ...

+0

Istnieje wersja 'wait', która wymaga limitu czasu, więc jeśli chcesz, aby czas procesora był tak często rejestrowany, użycie' 'wait (timeout)' jest łatwiejsze niż wprowadzenie 'Condition's. –

+0

@John Haager - dziękuję za wgląd, wstydzę się powiedzieć, że nie wiedziałem o tym – Yaneeve

+0

Wciąż - warunki są związane z Blokadami, i pozwalają ci robić bardziej interesujące rzeczy niż proste synchronizacje – Yaneeve

Powiązane problemy