tags:

views:

107

answers:

3

If I set a timer to execute a code every 3 seconds. If the code isn't finished in 3 seconds, what will happen? The computer will terminal the code or wait for the code finish or continue the timer, and execute the code with the unfinished code concurrently.

If the computer will execute the code with the unfinished code concurrently, what happen if a variable involve in the method. For example, the first line of run may doing i--, but last line is doing i++. If it run concurrently, when the unfinished code is still running, but a new running cycle is begin, the i value is being added by a new running cycle, so when the pervious cycle run to the last line, will the i value do wrong(because the new running cycle is doing i--, before the pervious code is finished). If yes, how to avoid it?

int delay = 0;   // delay for 0 sec.
int period = 3000;  // repeat 3 sec.
int i = 0;
Timer timer = new Timer();

timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            i--;
            // Task here ...
            // It may take more than 3 sec to finish, what will happen?
            i++;
        }
    }, delay, period);
+3  A: 

The code won't run concurrently. Read this: http://java.sun.com/javase/6/docs/api/java/util/Timer.html

Under scheduleAtFixedRate:

In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).

Pyrolistical
+1  A: 

Looking at the code, there is only one thread, so if the first run of the task takes more than 3 seconds, it will refire immediately after completion. Also note from the documentation:

In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up."

If you need it to start another thread you should look at ScheduledThreadPoolExecutor.

Kathy Van Stone
+4  A: 

Each Timer only uses one thread to service its tasks. The timer thread will run your task until it completes, and only then try to schedule its next execution. The documentation for Timer acknowledges this problem and warns its users against tasks "bunching up".

Once your task completes, the governing Timer will then attempt to schedule it again. The next scheduled execution will likely be in the past, per Timer$TimerThread#mainLoop()'s rescheduling policy: It adds the task's period to the last planned execution time of the task. Since in your case that planned execution time will be in the past by more than three seconds, adding three seconds to it still yields a next planned execution time in the past.

That's fine; the algorithm accommodates such slippage. Your task will run again immediately after the last run completes. What you won't get is your desired once-every-three-seconds behavior. Instead, you'll get as-often-as-possible-but-no-more-frequent-than-every-three-seconds.

seh