2010-06-23 17 views
5

Okumalarımdan, ScheduledExecutorService, Java'daki zamanlayıcıları başlatıp durdurmanın doğru yolu gibi görünüyor.Zamanlayıcısını başlatmak ve durdurmak için ScheduledExecutorService'ı kullanma

Zamanlayıcıyı başlatan ve durduran bazı kodları kullanmam gerekiyor. Bu periyodik bir zamanlayıcı değil. Bu kod, başlamadan önce zamanlayıcıyı durdurur. Yani, etkili bir şekilde her başlangıç ​​gerçekten bir yeniden başlatmadır(). ScheduledExecutorService kullanarak bunu yapmak için doğru yolu arıyorum. İşte neyle geldiğini. şeyleri ben eksik yapılan yorumlar ve anlayış Aranan:

ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(1); 
ScheduledFuture<?> _TimerFuture = null; 

private boolean startTimer() { 
    try { 
     if (_TimerFuture != null) { 
      //cancel execution of the future task (TimerPopTask()) 
      //If task is already running, do not interrupt it. 
      _TimerFuture.cancel(false); 
     } 

     _TimerFuture = _Timer.schedule(new TimerPopTask(), 
             TIMER_IN_SECONDS, 
             TimeUnit.SECONDS); 
     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 

private boolean stopTimer() { 
    try { 
     if (_TimerFuture != null) { 
      //cancel execution of the future task (TimerPopTask()) 
      //If task is already running, interrupt it here. 
      _TimerFuture.cancel(true); 
     } 

     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 

private class TimerPopTask implements Runnable { 
    public void run() { 
     TimerPopped(); 
    } 
} 

public void TimerPopped() { 
    //Do Something 
} 

tia, ruble

Bu sorun gibi görünüyor
+0

Kodu yazıldığı gibi derlenmez: startTimer() içindeki _batchTimer hiçbir yerde bildirilmez. Beklenen davranışlarda biraz daha ayrıntıya girebilmeniz yararlı olur: startTimer ve stopTimer öğelerinden dönüş değerleri nedir? Start/stopTimer'in aramaları potansiyel olarak engellemesini neden istiyorsunuz? – Sbodd

+0

@Sbodd, bir zamanlayıcıyı başlatmaya gittiğimde, zaten bir zamanlayıcı çalışıyorsa, bunu durdurmak istiyorum, böylece aynı anda iki zamanlayıcı yok. Ben get() orada yerine, sadece gelecekteki örneğinde cancel() çağırmak gerektiğini düşünüyorum. – rouble

cevap

3

:

Eğer iptal etmek yanlış geçiyoruz yana
private boolean startTimer() { 
    // ...... 
     if (_TimerFuture != null) { 
      _TimerFuture.cancel(false); 
     } 

     _TimerFuture = _Timer.schedule(new TimerPopTask(), 
             TIMER_IN_SECONDS, 
             TimeUnit.SECONDS); 
    // ...... 
} 

Görev zaten çalışıyorsa eski _TimerFuture iptal edilemeyebilir. Yine de yeni bir tane oluşturulur (ancak eşzamanlı olarak çalışmaz, çünkü ExecutorService'unuz sabit bir iş parçacığı havuzu boyutuna sahiptir). Her durumda, bu, startTimer() çağrıldığında bir zamanlayıcıyı yeniden başlatmayı istediğiniz davranış gibi gelmiyor.

Biraz araştırma yapabilirim. Ben TimerPopTask örneğini getirmek için "iptal" şey yapar ve ben oluşturulduktan sonra yalnız ScheduledFutures bırakacaktı: startTimer

private class TimerPopTask implements Runnable { 
    //volatile for thread-safety 
    private volatile boolean isActive = true; 
    public void run() { 
     if (isActive){ 
      TimerPopped(); 
     } 
    } 
    public void deactivate(){ 
     isActive = false; 
    } 
} 

sonra doğrusu ScheduledFuture örneğinin daha TimerPopTask örneğini elinde tutacak ve yeniden düzenlemek thusly yöntemi:

private TimerPopTask timerPopTask; 

private boolean startTimer() { 
    try { 
     if (timerPopTask != null) { 
      timerPopTask.deactivate(); 
     } 

     timerPopTask = new TimerPopTask(); 
     _Timer.schedule(timerPopTask, 
         TIMER_IN_SECONDS, 
         TimeUnit.SECONDS); 
     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 

(. stopTimer benzer modifikasyon() yöntemi)

sen gerçekten nee bekledikleri zaman parçacığı sayısını krank isteyebilir Ding 'yeniden başlatma' için zamanlayıcı geçerli süre dolmadan önce:

private ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(5); 

Ne açıklanan ve ayrıca geçerli ScheduledFuture olarak geçerli TimerPopTask hem başvurular tutarak melez bir yaklaşımla gitmek istiyorum ve en iyi hale getirebilir İptal etmek için garanti edilmediğini anlamak için iptali ve mümkünse ipliği boşaltmaya çalışın.

(Not:.. Bu bütün Aksi takdirde ek önlemler gerekir startTimer() ve stopTimer() yöntemi çağrıları tek ana iş parçacığı ile sınırlı olup, sadece TimerPopTask örnekleri parçacığı arasında paylaşılan varsayar)

+0

iyi nokta. Bunu sana sormama izin ver, bir görev çalışıyordu. Yeni bir görev oluşturuldu ve daha sonra TIMER_IN_SECONDS saniye çalışacak şekilde planlandı. Bu saat ne zaman (TIMER_IN_SECONDS saniye) başlar? Zamanlama() çağrıldığında VEYA iş parçacığı havuzunda boş bir iş parçacığı olduğunda işe yarayacak mı? – rouble

+0

Zamanlama() çağrıldığında TIMER_IN_SECONDS gecikme 'şimdi' başlar.Görevin gecikmeden daha erken başlaması garanti edilir, ancak daha sonra başlayabilir (parçanın kullanılabilirliğine bağlı olarak). ScheduledThreadPoolExecutor için javadoc'tan: "Geciken görevler, etkinleştirildiklerinden daha kısa sürede yürütmezler, ancak etkinleştirildikten sonra, ne zaman başlayacakları konusunda gerçek zamanlı bir garanti vermezler." –

İlgili konular