2009-06-25 11 views
17

Sto provando a utilizzare un timer per pianificare un evento ricorrente in un'applicazione. Tuttavia, voglio essere in grado di regolare il periodo in cui l'evento si attiva in tempo reale (in base all'input dell'utente).Java Timer

Ad esempio:

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; 
    } 
} 

ho quindi avviare una nuova istanza di questa classe e chiamare la sua funzione determinato periodo. Tuttavia, quando lo faccio, ottengo un'eccezione di stato illegale. Puoi vedere System.out.println (timer); lì perché sto controllando, e abbastanza sicuro, sono due timer diversi ... quindi perché sto ricevendo un IllegalStateException quando provo a eseguire una chiamata programmata su un'istanza Timer nuova di zecca!?!?!?!

[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) 

risposta

16

Non è possibile riutilizzare un TimerTask come si fa qui.

Rilevante porition di Timer:

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(); 
    } 
} 

Avrai bisogno di refactoring del codice in modo che si crea un nuovo TimerTask, piuttosto che ri-utilizzando uno.

+1

Come ha detto Kevin, si chiama "timer.schedule (questo, ritardo, punto)" con lo stesso "questo" ogni volta. Il TimerTask non è pensato per essere assegnato a più timer diversi. Ogni istanza TimerTask deve essere pianificata esattamente una volta. – Eddie

+1

Grazie, non è uscito completamente dalla documentazione e non appena sono passato alla creazione di nuovi TimerTasks, tutto è andato secondo i piani .. – Zak

+2

La specifica degli stati di pianificazione: @throws IllegalStateException se l'attività era già programmata o annullata, timer è stato annullato o il thread del timer è stato interrotto. L'attività era già pianificata in un timer precedente, quindi è stata generata l'eccezione. – notnoop

4

Mi sembra strano avere un TimerTask con il proprio Timer al suo interno. Cattivo design Separerei totalmente i due e far passare l'implementazione di TimerTask a un Timer, e metterei tutta la logica per manipolare il periodo all'interno di un'altra classe che fornisce un'interfaccia per farlo. Lascia che la classe istanzia il Timer e il TimerTask e mandali a fare il loro lavoro.

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

Per la prima volta, "Executed ...." verrà stampato dopo un ritardo di 4 secondi. Dopodiché, verrà stampato continuamente per ogni 3 secondi. – deeban