2009-06-25 7 views
17

私はタイマーを使ってアプリケーションで定期的なイベントをスケジュールしようとしています。しかし、私は、イベントが発生する時間を(ユーザーの入力に応じて)リアルタイムで調整できるようにしたいと考えています。例えばJavaタイマー

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

私は、このクラスの新しいインスタンスを起動し、その設定された期間の関数を呼び出します。しかし、私がそれをすると、私は不正な状態の例外を取得します。あなたはSystem.out.println(タイマー)を見ることができます。私がチェックしているので、十分に彼らは2つの異なったタイマーです...なぜ私は、新しいTimerインスタンスでスケジュール呼び出しを実行しようとするとIllegalStateExceptionを受け取りますか?

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

答えて

16

ここでやっているように、TimerTaskを再利用することはできません。 Timer

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

使用すると、1つの新しいTimerTaskをを作成するのではなく、再利用するようにあなたのコードをリファクタリングする必要があります。

+1

ケビンは言ったように、毎回同じ "this"で "timer.schedule(this、delay、period)"と呼んでいます。 TimerTaskは、複数の異なるタイマーに与えられることを意味しません。各TimerTaskインスタンスは、正確に1回スケジュールされることを意図しています。 – Eddie

+1

ありがとうございました、ドキュメント全体が飛び出すことはありません。新しいTimerTasksの作成に切り替えると、すべてが計画どおりに行われました.. – Zak

+2

スケジュールの指定は次のようになります:@throws IllegalStateException - タスクが既にスケジュールされているか、タイマースレッドが終了しました。 タスクは既に以前のTimerでスケジュールされていたため、例外がスローされました。 – notnoop

4

TimerTaskを内部に持つTimerTaskを持つのは奇妙に思えます。デザインが悪い。私は2つを完全に分離して、TimerTaskの実装をTimerに渡し、そのロジックを、別のクラスの中に時間を詰め込んで、そうするためのインターフェースを提供するようにします。そのクラスでTimerとTimerTaskをインスタンス化し、それらを送信して作業をさせます。

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

4秒後に "Executed ...."が最初に印刷されます。その後、3秒ごとに連続して印刷されます。 – deeban