Timer & TimerTask versus Thread + sleep in Java

Znalazłem podobne pytania zadawane tutaj, ale nie było odpowiedzi na moje zadowolenie. Więc przeformułowanie pytania ponownie -

Mam zadanie, które musi być wykonywane cyklicznie (powiedzmy 1-minutowe interwały). Jaka jest zaleta korzystania z 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ą wątku i uśpienia -

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

Naprawdę nie muszę się martwić, jeśli pomiń pewne cykle, jeśli wykonanie logiki zajmuje więcej niż czas interwału.

Skomentuj to..

Aktualizacja:
Ostatnio znalazłem kolejną różnicę między używaniem timera a wątkiem.sen (). Załóżmy, że obecny czas systemowy to 11: 00AM. Jeśli cofniemy czas systemowy do 10: 00am z jakiegoś powodu, Timer przestanie wykonywać zadanie, dopóki nie osiągnie 11:00am, podczas gdy wątek.metoda sleep () kontynuowałaby wykonywanie zadania bez przeszkód. Może to być główny decydent w decydowaniu, co wykorzystać między tymi dwoma.

Author: Keshav, 2009-09-21

7 answers

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

Zauważ, że może być napisany w krótszej formie, jak również własny przykład:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
 64
Author: Zed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-04 19:15:40

Timer / TimerTask uwzględnia również czas wykonania zadania, więc będzie on nieco dokładniejszy. I radzi sobie lepiej z kwestiami wielowątkowości (takimi jak unikanie impasów itp.). I oczywiście zazwyczaj lepiej jest użyć dobrze przetestowanego standardowego kodu zamiast jakiegoś domowego rozwiązania.

 12
Author: MartinStettner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-21 08:02:35

Nie wiem dlaczego, ale program, który pisałem, używał timerów i jego rozmiar stale wzrastał, gdy zmieniłem go na Thread/sleep problem rozwiązany.

 4
Author: Qandeel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-03 03:40:08

Jest jeden ważny argument przeciwko zarządzaniu tym zadaniem za pomocą wątków Javy i metody sleep. Używasz while(true), aby pozostać w pętli na czas nieokreślony i hibernować wątek poprzez uśpienie. Co jeśli NewUploadServer.getInstance().checkAndUploadFiles(); zajmie trochę zsynchronizowanych zasobów. Inne wątki nie będą mogły uzyskać dostępu do tych zasobów, co może spowolnić całą aplikację. Tego rodzaju błędy są trudne do zdiagnozowania i dobrze jest zapobiec ich istnieniu.

The other aproach uruchamia wykonanie kodu, który ma dla Ciebie znaczenie, tzn. NewUploadServer.getInstance().checkAndUploadFiles(); przez wywołanie metody run() twojego TimerTask, jednocześnie pozwalając innym wątkom korzystać z zasobów w międzyczasie.

 3
Author: Boris Pavlović,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-08 08:17:15

Jeśli wątek dostanie wyjątek i zostanie zabity, to jest problem. Ale TimerTask się tym zajmie. Będzie działać niezależnie od awarii w poprzednim biegu.

 3
Author: Stack Popper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 19:45:48

Myślę, że rozumiem twój problem, widzę coś bardzo podobnego. Mam zegary, które powtarzają się, niektóre co 30 minut, a niektóre co kilka dni. Z tego co czytam i widzę komentarze, wygląda na to, że garbage collection nigdy nie uruchomi się, ponieważ wszystkie zadania nigdy nie są ukończone. Myślałem, że śmieciarka będzie działać, gdy zegar jest w stanie uśpienia, ale ja tego nie widzę i zgodnie z dokumentacją nie.

Myślę, że tworzenie nowych wątków kończy się i umożliwić wywóz śmieci.

Niech ktoś mi udowodni, że się mylę, przepisanie tego, co odziedziczyłem, będzie bolało.

 1
Author: Ken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 03:24:48

Z Timer dokumentacja :

Java 5.0 wprowadziła Javę.util.pakiet współbieżny i jeden z narzędzia współbieżne to ScheduledThreadPoolExecutor, który jest pulą wątków do wielokrotnego wykonywania zadań w danym tempie lub opóźnienie. Jest to efektywnie bardziej wszechstronny zamiennik dla Połączenie Timer/TimerTask, ponieważ umożliwia wiele wątków serwisowych, akceptuje różne jednostki czasu i nie wymaga podklasowania TimerTask (tylko implementacja Runnable). Konfigurowanie ScheduledThreadPoolExecutor z jednym gwintem czyni go równoważnym timerowi.

Więc wolę ScheduledThreadExecutor zamiast Timer:

  • Timer używa pojedynczego wątku tła, który jest używany do wykonywania wszystkich zadań timera, sekwencyjnie. Tak więc zadania powinny zakończyć się szybko, inaczej opóźni to realizację kolejnych zadań. Ale w przypadku ScheduledThreadPoolExecutor możemy skonfigurować dowolną liczbę wątków i możemy również mieć pełną kontrolę poprzez dostarczenie ThreadFactory.
  • Timer może być wrażliwy na zegar systemowy, ponieważ korzysta z metody Object.wait(long). Ale nie jest.
  • wyjątki Runtime wrzucone do TimerTask zabijają ten konkretny wątek, co powoduje, że Timer jest martwy, ponieważ możemy obsłużyć to w ScheduledThreadPoolExecutor, Aby inne zadania nie miały wpływu.
  • Timer dostarcza cancel metodę do zakończenia timera i odrzucenia zaplanowanych zadań, jednak nie koliduje z aktualnie wykonywanym zadaniem i pozwala na jego zakończenie. Ale jeśli timer jest uruchomiony jako wątek demona, to niezależnie od tego, czy go anulujemy,czy nie, zakończy się jak tylko wszystkie wątki użytkownika zostaną zakończone.

Timer vs Thread.sen

Timer korzysta z Object.wait i różni się od Thread.sleep

  1. wątek oczekujący (wait) Może Być powiadomiony (używając notify) przez inny wątek, ale nie może być uśpiony, może być tylko przerwany.
  2. oczekiwanie (i powiadamianie) musi nastąpić w bloku zsynchronizowanym na obiekcie monitora, podczas gdy sen nie.
  3. podczas gdy sen nie zwalnia blokady, czekanie zwolni blokadę dla obiektu, na który jest wywoływany wait.
 0
Author: i_am_zero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 04:01:36