java.util.TimerTask cancel() method exact semantics

I am lost a bit with TimerTask cancel() method semantics comparing JavaDoc with real behaviour and source code.

JavaDoc says about return value:

Returns false if the task was scheduled for one-time execution and has already run, or if the task was never scheduled, or if the task was already cancelled.

However, looking into the code it looks like false maybe returned if a task has not already run yet, but will run. I'm looking at java.util.Timer code (mainLoop() method):

TimerTask task;
boolean taskFired;
synchronized(queue) {
    // Wait for queue to become non-empty
    while (queue.isEmpty() && newTasksMayBeScheduled)
        queue.wait();
    if (queue.isEmpty())
        break; // Queue is empty and will forever remain; die

    // Queue nonempty; look at first evt and do the right thing
    long currentTime, executionTime;
    task = queue.getMin();
    synchronized(task.lock) {
        if (task.state == TimerTask.CANCELLED) {
            queue.removeMin();
            continue;  // No action required, poll queue again
        }
        currentTime = System.currentTimeMillis();
        executionTime = task.nextExecutionTime;
        if (taskFired = (executionTime<=currentTime)) {
            if (task.period == 0) { // Non-repeating, remove
                queue.removeMin();
                task.state = TimerTask.EXECUTED;
            } else { // Repeating task, reschedule
                queue.rescheduleMin(
                  task.period<0 ? currentTime   - task.period
                                : executionTime + task.period);
            }
        }
    }
    if (!taskFired) // Task hasn't yet fired; wait
        queue.wait(executionTime - currentTime);
}
if (taskFired)  // Task fired; run it, holding no locks
    task.run();

It seems cancel() can be easily called right before the last if since TimerTask cancel() code just sets the task state apparently not synchronizing with task's run():

public boolean cancel() {
    synchronized(lock) {
        boolean result = (state == SCHEDULED);
        state = CANCELLED;
        return result;
    }
}

So, from my perspective the "loose" definition from JavaDoc given after the above appears to be strict indeed:

Loosely speaking, this method returns true if it prevents one or more scheduled executions from taking place.

So, again, it looks like getting false as cancel() method result might mean the task is not executed, but will be executed.

Please confirm my thinking or tell me where Im wrong.

Thank you!


Your understanding is correct, the false result clearly does not indicate that the task execution has completed, rather that it has started.

The most pedantic way to understand the phrase "task has already run" is "things have come to a point where the call to cancel failed to prevent the task from running". And, when you think about it, that is the information which the caller of cancel() is interested in.

So yes, I would also agree that the "loosely speaking" clause is stricter than the "strict" one.

Keep in mind that this Javadoc was written very early into the development of the Java platform and the standards for its quality have been increasing over time.


Basically I agree with you although it is quite extreme case.

So, again, it looks like getting false as cancel() method result might mean the task is not executed, but will be executed.

More precise would be "task is not executed, but will be executed immediately". But due to concurrency of threads it is useful simplification saying that the task is (at least) being executed. Thus second "definition" from javadoc looks more precise to me :)

If cancel() returns true, it means that the cancellation was successful in term that at least one further execution was prevented (either for one-time or repeated task) and false in all other cases.

链接地址: http://www.djcxy.com/p/74906.html

上一篇: 如何取消已安排的TimerTask?

下一篇: java.util.TimerTask cancel()方法的确切语义