Timer.cancel problem

R

Rick Genter

I am trying to do the following:

Timer timer = new Timer ();
timer.cancel ();

which is throwing an IllegalStateException. Why am I doing this? Well,
the actual code is obviously more complex; I have a queue of tasks that
I schedule, one at a time. I do not want to have multiple tasks
scheduled for the timer, since there could literally be tens of
thousands of them outstanding.

The queue is maintained in ascending order of scheduled completion. The
method that inserts an entry into the queue checks to see if it is
inserting at the head of the queue and, if so, cancels whatever is
currently pending and schedules the new task to fire. The problem, of
course, occurs when inserting the first entry.

According to the documentation on Timer.cancel():

"Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.

Note that calling this method from within the run method of a timer task
that was invoked by this timer absolutely guarantees that the ongoing
task execution is the last task execution that will ever be performed by
this timer.

This method may be called repeatedly; the second and subsequent calls
have no effect."

Any ideas?

Rick
 
N

NOBODY

I'm not sure if I understood your scenario but let's say
you have task a running and b and c waiting (a being the first, c the
last):

-you can already schedule timer tasks by time, I don't get what is that
queue of yours. -you should call task.cancel, not the timer.cancel.
-you can't cancel a running task, you would have to figure out the timer
thread by some twisked code, and at most call interrupt(), that you task
code should catch and handle. -if you wanted to cancel b and c together,
you must call b.cancel and c.cancel. If you have 10000 tasks, you would
call each cancel, and if it sounds stupid, maybe scheduling 10000 tasks
is too. You might want to write your own timer class that has some sort
of clearAllTasks() (and report the RFE to sun!)

note: timer uses the equivalent of an arraylist for holding tasks, so
inserts are fast, don't worry, but don't try to do your own timer with a
linkedlist!
 
N

NOBODY

-cancel the tasks, not the timer.
-if you don't want to cancel 10000 tasks, write your own timer and add a
clearAllTasks() method (but avoid linkedlist, you scheduling would be
too slow)

Bonus:
-you can't cancel a running task, but with some twisted code (one more
reason to write you own), you can grab the timerthread and .interrupt()
it. Write timertasks that grabs thread.currentThread() (the timerthread)
on entry and enhance your task class with a kill() method that simply
interrupt() the timer thread BUT... be sure to catch the
interruptedexception in your task run() code: you don't want to halt the
timer thread.

class MyTimerTask extends TimerTask {

Thread t;
final Object killtoken = "killtoken";

public void kill() {
synchronized(killtoken) {
if(t==null || t==Thread.currentThread())
throw new IllegalStateException("no thread/self-destruct
forbidden");
t.interrupt();
}
}


public void run() {
synchronized(this) {
t = Thread.currentThread();
}

try {
//code
} catch(InterruptedException e) {
} catch(EnterruptedIOException e) {
} finally {
synchronized(this) {
t = null;
}
}
}



}
 
N

NOBODY

(sorry for duplicates, if any, nntp problems...)

-cancel the tasks, not the timer.
-if you don't want to cancel 10000 tasks, write your own timer and add a
clearAllTasks() method (but avoid linkedlist, you scheduling would be too
slow)

Bonus:
-you can't cancel a running task, but with some twisted code (one more
reason to write you own), you can grab the timerthread and .interrupt()
it. Write timertasks that grabs thread.currentThread()
(the timerthread) on entry and enhance your task class with a kill()
method that simply interrupt() the timer thread BUT... be sure to catch
the interruptedexception in your task run() code: you don't want to halt
the timer thread.

public class MyTimerTask extends TimerTask {

Thread t;
final Object killtoken = "killtoken";

public void kill() {
synchronized(killtoken) {
if(t==null || t==Thread.currentThread())
throw new IllegalStateException("no thread/self-
destruct forbidden");
t.interrupt();
}
}

public void run() {
synchronized(this) {
t = Thread.currentThread();
}

try {
//code....
} catch(InterruptedException e) {
} catch(EnterruptedIOException e) {
} finally {
synchronized(this) {
t = null;
}
}
}
}
 
N

NOBODY

(sorry for duplicates, nntp server problems...)

-cancel the tasks, not the timer.
-if you don't want to cancel 10000 tasks, write your own timer and add a
clearAllTasks() method (but avoid linkedlist, you scheduling would be
too slow)

Bonus:
-you can't cancel a running task, but with some twisted code (one more
reason to write you own), you can grab the timerthread and .interrupt()
it. Write timertasks that grabs thread.currentThread() (the timerthread)
on entry and enhance your task class with a kill() method that simply
interrupt() the timer thread BUT... be sure to catch the
interruptedexception in your task run() code: you don't want to halt the
timer thread.

public class MyTimerTask extends TimerTask {

Thread t;
final Object killtoken = "killtoken";

public void kill() {
synchronized(killtoken) {
if(t==null || t==Thread.currentThread())
throw new IllegalStateException("no thread/self-
destruct
forbidden"); t.interrupt();
}
}

public void run() {
synchronized(this) {
t = Thread.currentThread();
}

try {
//code....
} catch(InterruptedException e) {
} catch(EnterruptedIOException e) {
} finally {
synchronized(this) {
t = null;
}
}
}
}
 
J

Jim

I am trying to do the following:

Timer timer = new Timer ();
timer.cancel ();

which is throwing an IllegalStateException. Why am I doing this? Well,
the actual code is obviously more complex; I have a queue of tasks that
I schedule, one at a time. I do not want to have multiple tasks
scheduled for the timer, since there could literally be tens of
thousands of them outstanding.

The queue is maintained in ascending order of scheduled completion. The
method that inserts an entry into the queue checks to see if it is
inserting at the head of the queue and, if so, cancels whatever is
currently pending and schedules the new task to fire. The problem, of
course, occurs when inserting the first entry.

According to the documentation on Timer.cancel():

"Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.

Note that calling this method from within the run method of a timer task
that was invoked by this timer absolutely guarantees that the ongoing
task execution is the last task execution that will ever be performed by
this timer.

This method may be called repeatedly; the second and subsequent calls
have no effect."

Any ideas?

Rick
You're not trying to reuse the Timer instance after cancel()ing it are
you? Just wondering because cancel() doesn't throw any exceptions
and all of the schedule methods do throw an IllegalStateException
"if task was already scheduled or cancelled, timer was cancelled, or
timer thread terminated."

Your description of you "head" insert seems to imply that you're
trying to rescedule on the canceled Timer instance.

Jim
 
D

Dale King

Rick Genter said:
I am trying to do the following:

Timer timer = new Timer ();
timer.cancel ();

which is throwing an IllegalStateException. Why am I doing this? Well,
the actual code is obviously more complex; I have a queue of tasks that
I schedule, one at a time. I do not want to have multiple tasks
scheduled for the timer, since there could literally be tens of
thousands of them outstanding.

Why not?
The queue is maintained in ascending order of scheduled completion. The
method that inserts an entry into the queue checks to see if it is
inserting at the head of the queue and, if so, cancels whatever is
currently pending and schedules the new task to fire. The problem, of
course, occurs when inserting the first entry.

So instead of using the queue that maintains a heap of tasks arranged by
order of scheduled completion (a heap is faster than maintaining them in a
sorted list), you somehow feel compelled to try to do it yourself.

What you want is already built into Timer. Just go ahead and schedule all of
the tasks. The fact that there are tens of thousands is not really a
problem.
According to the documentation on Timer.cancel():

"Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.

Note that calling this method from within the run method of a timer task
that was invoked by this timer absolutely guarantees that the ongoing
task execution is the last task execution that will ever be performed by
this timer.

This method may be called repeatedly; the second and subsequent calls
have no effect."

Any ideas?

As others have noted that when you cancel the Timer, then that Timer is
finished and can never be used again.
 
R

Rick Genter

Jim said:
On Sat, 03 Jan 2004 10:47:44 -0500, Rick Genter

You're not trying to reuse the Timer instance after cancel()ing it are
you? Just wondering because cancel() doesn't throw any exceptions
and all of the schedule methods do throw an IllegalStateException
"if task was already scheduled or cancelled, timer was cancelled, or
timer thread terminated."

Your description of you "head" insert seems to imply that you're
trying to rescedule on the canceled Timer instance.

Jim

Thanks, this was exactly it. Since others have indicated that tens of
thousands of tasks should not be a problem, I'll go ahead and try to use
the timer "as intended."

Thanks again.

Rick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top