Timer & TimerTask ve Java'da Thread + uyku


102

Burada sorulan benzer soruları buldum ama memnuniyetime cevap vermedi. Öyleyse soruyu yeniden ifade etmek-

Periyodik olarak (1 dakikalık aralıklarla) yapılması gereken bir görevim var. Uyku ile sonsuz döngüye sahip yeni bir iş parçacığı oluşturmanın aksine bunu yapmak için Timertask & Timer kullanmanın avantajı nedir?

Timertask kullanarak kod parçacığı-

TimerTask uploadCheckerTimerTask = new TimerTask(){

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

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

İş Parçacığı ve uyku kullanarak kod parçacığı

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

Mantığın yürütülmesi aralık süresinden daha uzun sürerse, belirli döngüleri kaçırırsam gerçekten endişelenmeme gerek yok.

Lütfen buna yorum yapın ..

Güncelleme:
Son zamanlarda Timer ile Thread.sleep () arasında başka bir fark buldum. Mevcut sistem saatinin 11:00 AM olduğunu varsayalım. Herhangi bir nedenle sistem saatini 10: 00'a geri alırsak, Timer görevi 11: 00'a ulaşana kadar DURDURACAK, oysa Thread.sleep () yöntemi engel olmadan görevi yürütmeye devam edecektir. Bu, bu ikisi arasında ne kullanılacağına karar verirken önemli bir karar verici olabilir.


21
Sıra noktası: Timer ve TimerTask artık kullanılmıyor ve amacınız hala geçerli olmasına rağmen, ExecutorService ile etkili bir şekilde değiştirildi.
skaffman

Bahşiş için teşekkürler, ExecutorService'i kullanmaya karar verdim :)
Keshav

Cevaplar için hepinize teşekkür ederim, kesinlikle bana daha fazla anlayış verdi!
Keshav

6
Zamanlayıcı eski değildir ve yalnızca tek bir iş parçacığına ihtiyaç duyulduğunda tercih edilir. ( java.sun.com/javase/6/docs/api/java/util/Timer.html )
Justin

2
Timer ve TimerTask, ExecutorService'in bulunmadığı JME ortamlarında hala yararlıdır (JME Java 1.3 tabanlı ...).
ス ー パ ー フ ァ ミ コ ン

Yanıtlar:


67

TimerTask'ın avantajı, niyetinizi çok daha iyi ifade etmesi (yani kod okunabilirliği) ve zaten cancel () özelliğine sahip olmasıdır.

Kendi örneğinizin yanı sıra daha kısa bir biçimde de yazılabileceğini unutmayın:

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

Eğer zamanlayıcı Her gün, 2 belirli saatte 9:00 ve 09:00 için kullanılıyorsa, ... değerler nasıl verilir? yukarıdaki kodda ... @Zed?
gumuruh

12

Timer / TimerTask, görevinizin gerçekleştirilme süresini de hesaba katar, bu nedenle biraz daha doğru olacaktır. Ve çoklu okuma sorunlarıyla daha iyi ilgilenir (kilitlenmelerden kaçınma vb.). Ve elbette, bazı ev yapımı çözümler yerine iyi test edilmiş standart kod kullanmak daha iyidir.


5

Nedenini bilmiyorum ama yazdığım bir program Zamanlayıcılar kullanıyordu ve yığın boyutu sürekli olarak artıyordu, onu Thread / sleep problemi olarak değiştirdiğimde.


9
Zamanlayıcı, sürekli güncellenen bir görev sırası oluşturur. Zamanlayıcı tamamlandığında, hemen çöp toplanmayabilir. Bu nedenle, daha fazla Zamanlayıcı oluşturmak, yalnızca yığına daha fazla nesne ekler. Thread.sleep () yalnızca iş parçacığını duraklatır, bu nedenle bellek ek yükü çok düşük olur.
Darryl Gerrow

4

İş parçacığı istisna olursa ve öldürülürse, bu bir sorundur. Ancak TimerTask bununla ilgilenecek. Önceki çalıştırmadaki hatadan bağımsız olarak çalışacaktır.


4

Gönderen Timer belgeler :

Java 5.0, java.util.concurrent paketini tanıttı ve buradaki eşzamanlılık yardımcı programlarından biri, görevleri belirli bir hızda veya gecikmede tekrar tekrar yürütmek için bir iş parçacığı havuzu olan ScheduledThreadPoolExecutor'dur. Birden çok hizmet iş parçacığına izin verdiği, çeşitli zaman birimlerini kabul ettiği ve alt sınıflandırma TimerTask gerektirmediğinden (sadece Runnable'ı uyguladığından) Timer / TimerTask kombinasyonu için etkili bir şekilde daha çok yönlü bir alternatiftir. ScheduledThreadPoolExecutor'ı bir iş parçacığı ile yapılandırmak, Timer ile eşdeğer olmasını sağlar.

Bu yüzden ScheduledThreadExecutorbunun yerine tercih edin Timer:

  • TimerZamanlayıcının tüm görevlerini sırayla yürütmek için kullanılan tek bir arka plan iş parçacığı kullanır. Dolayısıyla görevler hızlı bir şekilde tamamlanmalıdır, aksi takdirde sonraki görevlerin yürütülmesini geciktirir. Ancak ScheduledThreadPoolExecutorherhangi bir sayıda iş parçacığı yapılandırabilir ve sağlayarak tam kontrole sahip olabiliriz ThreadFactory.
  • TimerObject.wait(long)yöntemi kullandığı için sistem saatine duyarlı olabilir . Ama ScheduledThreadPoolExecutordeğil.
  • TimerTask'ta atılan çalışma zamanı istisnaları o belirli iş parçacığını öldürecektir, böylece Timer'ı ScheduledThreadPoolExecutor, diğer görevlerin etkilenmemesi için halledebildiğimiz yerde öldürecektir .
  • Timersağlayan cancelzamanlayıcı feshedebilir ve zamanlanmış görevler atmak yöntemi, ancak şu anda yürütülen bir görev müdahale ve onu bitirmek izin vermez. Ancak zamanlayıcı daemon evresi olarak çalışıyorsa, iptal etsek de etmesek de, tüm kullanıcı evrelerinin yürütülmesi biter bitmez sona erecektir.

Timer vs Thread.sleep

Zamanlayıcı kullanır Object.waitve farklıdırThread.sleep

  1. Bir bekleyen ( wait) iş parçacığı notifybaşka bir iş parçacığı tarafından bildirilebilir (kullanılarak ) ancak uyuyan bir iş parçacığı olamaz, yalnızca kesilebilir.
  2. Bekleme (ve bildirim) monitör nesnesinde senkronize edilmiş bir blokta gerçekleşmelidir, oysa uyku değildir.
  3. Uyku, kilidi açmazken, beklemek, nesne için kilidi açacaktır, bekleme çağrısı yapılır.

çok yararlı bilgiler, Plus sonsuz döngüde Thread.sleep kullanılması, düşük zaman gecikmelerinde yüksek CPU kullanımına neden olabilir.
Amir Fo

3

Bu görevi Java iş parçacıkları ve sleepyöntemini kullanarak yönetmeye karşı çok önemli bir argüman var . Kullandığınız while(true)döngüde süresiz kalmak ve uyumaya koyarak parçacığı hazırda bekletme. Ya NewUploadServer.getInstance().checkAndUploadFiles();senkronize edilmiş bazı kaynakları alırsa . Diğer iş parçacıkları bu kaynaklara erişemeyecek, açlık olabilir ve bu da tüm uygulamanızı yavaşlatabilir. Bu tür hataların teşhis edilmesi zordur ve bunların varlığını önlemek iyi bir fikirdir.

Diğer yaklaşım, sizin için önemli olan kodun yürütülmesini tetikler, yani , bu arada kaynakları kullanan diğer iş parçacıklarına izin verirken sizin yönteminizi NewUploadServer.getInstance().checkAndUploadFiles();çağırarak .run()TimerTask


16
Bu argümanı anlamıyorum. Her iki seçenek de aynı yöntemi bir iş parçacığından başlatır, her iki seçenek de yürütmeyi beklerken bir iş parçacığında uyur. İki seçenek arasında açlık farkı olmayacak.
satur9nine

2

Sanırım sorununuzu anlıyorum, çok benzer bir şey görüyorum. Bazıları her 30 dakikada bir ve bazıları her iki günde bir tekrarlayan zamanlayıcılarım var. Okuduklarımdan ve gördüğüm yorumlardan, çöp toplama asla çalışmayacak gibi görünüyor çünkü tüm görevler asla tamamlanmadı. Bir zamanlayıcı uykudayken çöp toplamanın çalışacağını düşünürdüm, ancak onu görmüyorum ve belgelere göre değil.

Yeni iş parçacığı üretmenin tamamlandığını ve çöp toplamaya izin verdiğini düşünüyorum.

Lütfen birisi bana yanıldığını kanıtlasa, miras aldığım şeyi yeniden yazmak acı verici olacak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.