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 (타이머)를 볼 수 있습니다. 거기에서 내가 확인하고 있기 때문에 충분히 확실해, 그들은 두 개의 다른 타이머 ... 그래서 내가 왜 새로운 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(); 
    } 
} 
오히려 일을 다시 사용하는 것보다, 새로운의 TimerTask를 만들 수 있도록 당신은 당신의 코드를 리팩토링해야합니다

.

+1

Kevin이 말한 것처럼 매번 같은 "this"를 사용하여 "timer.schedule (this, delay, period)"를 호출합니다. TimerTask는 여러 다른 타이머에 제공되지 않습니다. 각 TimerTask 인스턴스는 정확히 한 번 예약해야합니다. – Eddie

+1

고마워, 완전히 문서에서 튀어 나오지 않고 새로운 TimerTasks를 생성하자마자 모든 것이 계획대로 진행되었습니다 .. – Zak

+2

일정의 상태는 다음과 같습니다 : @throws IllegalStateException - 작업이 이미 예약되거나 취소 된 경우 타이머 취소되었거나 타이머 스레드가 종료되었습니다. 작업이 이미 이전 타이머에서 예약되었으므로 예외가 throw됩니다. – notnoop

4

내부 타이머가있는 TimerTask를 갖는 것이 이상한 것 같습니다. 나쁜 디자인. 두 개를 완전히 분리하고 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

처음으로 "Executed ...."는 4 초 지연 후 인쇄됩니다. 그 후, 3 초마다 계속해서 인쇄됩니다. – deeban