2013-07-24 17 views
16

Przepraszam za to powtarzające się pytanie, ale nie znalazłem jeszcze zadowalających odpowiedzi. Większość kwestii miał swój specyficzny przypadek użycia:
Java - alternative to thread.sleep
Is there any better or alternative way to skip/avoid using Thread.sleep(1000) in Java?Dlaczego Thread.sleep jest zły w użyciu

moje pytanie jest za bardzo rodzajowe przypadku użycia. Poczekaj na zakończenie warunku. Wykonaj jakąś operację. Sprawdź stan. Jeśli warunek nie jest spełniony, odczekaj chwilę i ponownie wykonaj tę samą operację.

Dla np. Rozważmy metodę, która tworzy tabelę DynamoDB, wywołując jej tablicę createAPI. Tabela DynamoDB zajmuje trochę czasu, aby zostać aktywnym, aby metoda wywoływała jego interfejs DescribeTable API w celu odpytywania o status w regularnych odstępach czasu do pewnego czasu (powiedzmy 5 minut - dopuszczalne odchylenie z powodu planowania wątków jest dopuszczalne). Zwraca wartość true, jeśli tabela stanie się aktywna w ciągu 5 minut, w przeciwnym razie zgłasza wyjątek.

Oto pseudokod:

public void createDynamoDBTable(String name) { 
    //call create table API to initiate table creation 

    //wait for table to become active 
    long endTime = System.currentTimeMillis() + MAX_WAIT_TIME_FOR_TABLE_CREATE; 

    while(System.currentTimeMillis() < endTime) { 
    boolean status = //call DescribeTable API to get status; 
    if(status) { 
     //status is now true, return 
     return 
    } else { 
     try { 
      Thread.sleep(10*1000); 
     } catch(InterruptedException e) { 
     } 
    } 
    } 

    throw new RuntimeException("Table still not created"); 
} 

Rozumiem, że za pomocą Thread.sleep blokuje bieżącego wątku, dzięki czemu zużywa zasobów. ale w dość średniej wielkości aplikacji jeden wątek jest poważnym problemem?
Czytam gdzieś, że używają ScheduledThreadPoolExecutor i wykonuję tam odpytywanie o statusie. Ale znowu, musielibyśmy zainicjować tę pulę z co najmniej jednym wątkiem, w którym uruchomiłaby się możliwa do uruchomienia metoda odpytywania.

Wszelkie sugestie, dlaczego użycie Thread.sleep jest tak złym pomysłem i jakie są alternatywne opcje osiągnięcia tego samego, co powyżej.

http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

+2

http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx – stinepike

+4

Twój link jest o .Net. Nie dotyczy Java. –

+0

Sondowanie jest złe, bez wątpienia. Ale jeśli nie masz alternatywy, to jest najmniejsza rzecz, o którą powinieneś się troszczyć. –

Odpowiedz

24

Dobrze jest używać Thread.sleep w tej sytuacji. Powodem, dla którego ludzie zniechęcają użytkowników do próbnej naprawy warunków wyścigu, są te, w których synchronizacja z powiadomieniami jest znacznie lepszym wyborem.

W tym przypadku AFAIK nie ma opcji, ale sonda ponieważ interfejs API nie zapewnia powiadomień. Widzę też, że jest to operacja nieczęsta, ponieważ prawdopodobnie nie zamierzasz stworzyć tysiąca tabel.

Dlatego uważam, że dobrze jest tutaj użyć Thread.sleep. Jak już powiedziałeś, tworzenie osobnego wątku, gdy zamierzasz zablokować bieżący wątek, wydaje się skomplikować rzeczy bez zasług.

+9

Jedno duże zastrzeżenie: upewnij się, że śpiący wątek nie trzyma ograniczonych zasobów, takich jak połączenie mutex lub baza danych. – yshavit

+0

Czy ten wzorzec byłby również dopuszczalny w następującym przypadku? - Wypytywanie SQS dla jednej wiadomości na raz i utrzymywanie listy wiadomości. Gdy rozmiar listy osiągnie liczbę X, przetwarzaj je zbiorczo. Jeśli nie ma więcej wiadomości w SQS, przespać się przez jakiś czas. Ponownie sonduj po tym. – RandomQuestion

+0

@Jitendra: Zwykle z MQ, których chcesz uniknąć odpytywania, ale AFAIK, nie ma innego sposobu niż odpytywanie w SQS (które, nawiasem mówiąc, pobierają, nawet gdy nie ma żadnej wiadomości), więc 'Thread.sleep' jest opcja. Mogę być skłonny do korzystania z harmonogramu executorów, ponieważ ułatwia to dodawanie klientów, dopracowanie planowania głosowania i zmusza do oddzielenia logiki biznesowej i infrastruktury. –

2

Tak, powinno się unikać używania Thread.Sleep (x), ale to nie powinno być całkowicie zapomniane:

Dlaczego należy unikać

  • To nie zwalnia blokadę
  • nie Gwarantujemy, że realizacja rozpocznie się po raz śpi (Więc może zachować czekając na zawsze - oczywiście rzadki przypadek)
  • Jeśli błędnie umieścić pierwszoplanowy wątek przetwarzania na sen potem wo nie będziesz w stanie zamknąć tej aplikacji do x milisekund.
  • Mamy teraz pełny załadowany nowy pakiet współbieżności dla konkretnych problemów (jak wzorce projektowe (ofcourse not dokładnie), dlaczego warto użyć Thread.sleep (x).

Gdzie używać Thread.Sleep (x):

  • Dla zapewnienia opóźnienia w tle uruchomiony wątków
  • I kilka innych.
+0

Nie używaj formatowania cytatów dla tekstu, który nie jest cytowany. – EJP