2009-06-25 20 views
17

Bir uygulamada yinelenen bir olay zamanlamak için bir zamanlayıcı kullanmaya çalışıyorum. Ancak, olayın gerçek zamanlı olarak (kullanıcı girdisine göre) hareket ettiği süreyi ayarlayabilmek istiyorum. ÖrneğinJava Timer

:

public class HelperTimer extends TimerTask 
{ 
    private Timer timer; 
    //Default of 15 second between updates 
    private int secondsToDelay = 15; 

    public void setPeriod(int seconds) 
    { 
     this.secondsToDelay = seconds; 
     long delay = 1000; // 1 second 
     long period = 1000*secondsToDelay; // seconds 
     if (timer != null) 
     { 
      timer.cancel(); 
     } 
     System.out.println(timer); 
     timer = new Timer(); 
     System.out.println(timer); 
     timer.schedule(this, delay, period); 
    } 
    public int getPeriod() 
    { 
     return this.secondsToDelay; 
    } 
} 

Sonra bu sınıfın yeni bir örneğini başlatmak ve süre belirleme işlevini çağırın. Ancak, bunu yaptığımda Yasa dışı bir durum istisnası alıyorum. System.out.println (zamanlayıcı) görebilirsiniz; Orada kontrol ettiğimden ve yeterince emin olduğumdan, iki farklı zamanlayıcılar ... neden yeni bir Timer örneğinde bir program çağrısı çalıştırmayı denediğimde neden bir IllegalStateException alıyorum!?!?!?!

[email protected] 
[email protected] 
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled 
    at java.util.Timer.sched(Unknown Source) 
    at java.util.Timer.schedule(Unknown Source) 
    at HelperTimer.setPeriod(HelperTimer.java:38) 

cevap

16

Burada yaptığınız gibi bir TimerTask'ı yeniden kullanamazsınız. Timer ait

İlgili porition:

private void sched(TimerTask task, long time, long period) { 
    if (time < 0) 
     throw new IllegalArgumentException("Illegal execution time."); 

    synchronized(queue) { 
     if (!thread.newTasksMayBeScheduled) 
      throw new IllegalStateException("Timer already cancelled."); 

     synchronized(task.lock) { 
      //Right here's your problem. 
      // state is package-private, declared in TimerTask 
      if (task.state != TimerTask.VIRGIN) 
       throw new IllegalStateException(
        "Task already scheduled or cancelled"); 
      task.nextExecutionTime = time; 
      task.period = period; 
      task.state = TimerTask.SCHEDULED; 
     } 

     queue.add(task); 
     if (queue.getMin() == task) 
      queue.notify(); 
    } 
} 
Bunun yerine teker yeniden kullanmak yerine, yeni bir TimerTask oluşturmak, böylece kodunuzu gözden geçirmeniz gerekir

.

+1

Kevin'in dediği gibi, "timer.schedule (bu, gecikme, nokta)" ifadesini her seferinde aynı "bu" ile çağırıyorsunuz. TimerTask, birden fazla farklı zamanlayıcıya verilmek zorunda değildir. Her bir TimerTask örneğinin tam olarak bir defa planlanması gerekir. – Eddie

+1

Teşekkürler, bu tamamen dokümantasyondan çıkmıyor ve yeni TimerTasks oluşturmaya geçtiğimde, her şey plana göre değişti .. – Zak

+2

Zamanlama durumlarının belirtimi: Görev zaten planlanmış veya iptal edilmişse, @throws İllegalStateException iptal edildi veya zamanlayıcı iş parçacığı sonlandırıldı. Görev zaten daha eski bir Zamanlayıcısında planlanmıştı, dolayısıyla istisna atılıyordu. – notnoop

4

İçinde kendi Zamanlayıcısı olan bir TimerTask olması garip görünüyor. Kötü tasarım İkisini tamamen ayıracağım ve TimerTask uygulamasının bir Zamanlayıcı'ya teslim edilmesini ve tüm bu mantığın, bunu yapmak için bir arabirim sağlayan başka bir sınıfın içindeki dönemle karıştırmasını istiyorum. Bu sınıfın Timer ve TimerTask'ı başlatmasına ve işlerini yapmak için onları göndermesine izin verin.

0
import java.util.*; 
    class TimeSetting 
    { 
    public static void main(String[] args) 
    { 
    Timer t = new Timer(); 
    TimerTask time = new TimerTask() 
    { 
    public void run() 
    { 
    System.out.println("Executed......"); 
    } 
    }; 
    t.scheduleAtFixedRate(time, 4000, 3000); 
    // The task will be started after 4 secs and 
    // for every 3 seconds the task will be continuously executed..... 
    } 
    } 
+0

İlk kez, "Executed ...." 4 saniye gecikme sonrasında yazdırılacak .. Bundan sonra, her 3 saniye için sürekli basılacaktır. – deeban

İlgili konular