2009-09-21 11 views
95

Znalazłem podobne pytania tutaj, ale nie było odpowiedzi na moje zadowolenie. Ponownie przeformułując pytanie -Timer i TimerTask kontra wątek + sen w Javie

Mam zadanie, które musi być wykonywane okresowo (powiedzmy co 1 minutę). Co jest zaletą Timertask & Timer, aby to zrobić w przeciwieństwie do tworzenia nowego wątku, który ma nieskończoną pętlę ze snem?

Fragment kodu przy użyciu timertask-

TimerTask uploadCheckerTimerTask = new TimerTask(){ 

public void run() { 
    NewUploadServer.getInstance().checkAndUploadFiles(); 
} 
}; 

Timer uploadCheckerTimer = new Timer(true); 
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000); 

fragment kodu za pomocą nici i Sleep and

Thread t = new Thread(){ 
public void run() { 
    while(true) { 
    NewUploadServer.getInstance().checkAndUploadFiles(); 
    Thread.sleep(60 * 1000); 
    } 
} 
}; 
t.start(); 

I naprawdę nie trzeba się martwić, jeśli pominąć pewne cykle, jeśli wykonanie logiki trwa więcej niż interwał.

Proszę o komentarz w tej sprawie ..

Dzięki
-Keshav

Aktualizacja:
Ostatnio znalazłem inną różnicę pomiędzy użyciem timera kontra Thread.Sleep(). Załóżmy, że obecny czas systemowy to 11:00. Jeśli z jakiegoś powodu wycofamy czas systemowy do godziny 10:00, program Timer wykona polecenie STOP, dopóki nie osiągnie godziny 11:00, natomiast metoda Thread.sleep() będzie kontynuowała wykonywanie zadania bez przeszkód. Może to być głównym decydentem przy podejmowaniu decyzji, co stosować między tymi dwoma.

+21

Punkt porządku: Timer i TimerTask są przestarzałe i zostały skutecznie zastąpione przez ExecutorService, chociaż twój punkt nadal jest ważny. – skaffman

+0

Dzięki za podpowiedź, zdecydowałem się użyć ExecutorService :) – Keshav

+0

Dziękuję wszystkim za odpowiedzi, na pewno dałem mi więcej zrozumienia! – Keshav

Odpowiedz

63

Zaletą TimerTask jest to, że znacznie lepiej wyraża ona intencję (tj. Czytelność kodu) i ma już zaimplementowaną funkcję cancel().

Należy pamiętać, że może to być napisane w krótszej formie, jak i swoim własnym przykładzie:

Timer uploadCheckerTimer = new Timer(true); 
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() { 
     public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); } 
    }, 0, 60 * 1000); 
+0

jeśli licznik jest używany na co dzień, w 2 określonym czasie 21 i 9, ... jak podać wartości? na powyższym kodzie ... @Zed? – gumuruh

11

Timer/TimerTask uwzględnia również czas wykonania swojego zadania, więc będzie nieco bardziej dokładne . I radzi sobie lepiej z kwestiami wielowątkowymi (takimi jak unikanie zakleszczeń itp.). Oczywiście zwykle lepiej jest używać sprawdzonego standardowego kodu zamiast jakiegoś domowego rozwiązania.

+0

To bardzo dobry punkt, dziękuję. – Ridcully

3

Istnieje jeden zasadniczy argument przeciwko zarządzaniu tym zadaniem przy użyciu wątków Java i metody sleep. Używasz while(true), aby pozostać w pętli bez końca i hibernować wątek poprzez uśpienie. Co jeśli NewUploadServer.getInstance().checkAndUploadFiles(); przejmuje niektóre zsynchronizowane zasoby. Inne wątki nie będą miały dostępu do tych zasobów, może dojść do głodzenia, co może spowolnić całą twoją aplikację. Tego typu błędy są trudne do zdiagnozowania i dobrze jest zapobiegać ich istnieniu.

Drugi aproach wyzwala wykonanie kodu, który liczy się dla ciebie, to znaczy NewUploadServer.getInstance().checkAndUploadFiles(); wywołując metodę run() swój TimerTask jednocześnie pozwalając inne wątki wykorzystaniem zasobów w międzyczasie.

+16

Nie rozumiem tego argumentu. Oba wybory uruchamiają tę samą metodę z wątku, oba wybory śpią w wątku podczas oczekiwania na wykonanie. Nie będzie żadnych różnic głodowych między tymi dwoma wyborami. – satur9nine

4

Nie wiem dlaczego, ale program, który pisałem, korzystał z liczników czasu, a jego wielkość stale rosła, kiedy zmieniłem go na problem z wątkiem/uśpieniem.

+6

Program minutnik tworzy kolejkę zadań, która jest stale aktualizowana. Po zakończeniu licznika czasu może nie zostać natychmiast zebrany. Tworzenie więcej Timerów dodaje więcej obiektów na stercie. Thread.sleep() zatrzymuje tylko wątek, więc narzut pamięci byłby bardzo niski. –

3

Jeśli wątek zostanie zgłoszony jako wyjątek i zostanie zabity, oznacza to problem. Ale TimerTask zajmie się tym. Będzie działał niezależnie od awarii w poprzednim przebiegu.

1

Myślę, że rozumiem twój problem, widzę coś bardzo podobnego. Mam zegary, które się powtarzają, niektóre co 30 minut, a niektóre co kilka dni. Z tego, co przeczytałem i komentarzy, które widzę, wygląda na to, że odśmiecanie nigdy się nie uruchomi, ponieważ wszystkie zadania nigdy nie są kompletne. Wydaje mi się, że odbiór śmieci byłby uruchamiany, gdy zegar jest w stanie uśpienia, ale nie widzę go i zgodnie z dokumentacją nie jest.

Wydaje mi się, że nowe wątki kończą się i pozwalają na odśmiecanie.

Ktoś proszę mnie udowodnić, przepisanie tego, co odziedziczyłem, będzie bólem.