Re: How can I stop an anonymous thread?

D

Dave Glasser

I tend to use anonymous objects (and therefore anony-
mous threads) quite often. But how does one stop an
anonymous thread. In the following program I invoke
the garbage collector to stop the unreferenced Timer
thread?

How would you prefer to write this program?

George W. Cherry

import java.util.Timer;
import java.util.TimerTask;

public class AlarmClock {
public static void main(String[] args) {
int delay = Integer.parseInt( args[0] );
System.out.println(
"Setting alarm clock to go off " + delay + " seconds from now."
);
new Timer().schedule(
new TimerTask() {
public void run() {
System.out.println("Ding-A-Ling! Time to get up!");
}
},
delay*1000
);
System.gc(); //To shut down the anonymous Timer thread.
}//end main method
}//end AlarmClock class

First, invoking the garbage collector will not stop an anonymous
thread, nor will it arbitrarily stop any running thread; if it did
then Java would pretty worthless.

Your anonymous thread could be given a reference to a variable outside
of itself (in the enclosing class) which it could check periodically
to see if it should continue running.

Or, you could just hold on to a reference to your Timer object and
call its cancel method when/if you want to stop it:

Timer t = new Timer().schedule(
...

t.cancel();
 
G

George W. Cherry

Dave Glasser said:
I tend to use anonymous objects (and therefore anony-
mous threads) quite often. But how does one stop an
anonymous thread. In the following program I invoke
the garbage collector to stop the unreferenced Timer
thread?

How would you prefer to write this program?

George W. Cherry

import java.util.Timer;
import java.util.TimerTask;

public class AlarmClock {
public static void main(String[] args) {
int delay = Integer.parseInt( args[0] );
System.out.println(
"Setting alarm clock to go off " + delay + " seconds from now."
);
new Timer().schedule(
new TimerTask() {
public void run() {
System.out.println("Ding-A-Ling! Time to get up!");
}
},
delay*1000
);
System.gc(); //To shut down the anonymous Timer thread.
}//end main method
}//end AlarmClock class

First, invoking the garbage collector will not stop an anonymous
thread, nor will it arbitrarily stop any running thread; if it did
then Java would pretty worthless.

But "System.gc();" works! Run it and see. Then comment out
the invocation of the garbage collector, compile it, and run it;
and you'll see that the program "hangs". In all fairness to your
claim, Dave, an invocation of the gc on an anonymous thread
that HAS REACHED THE END of its run method will collect
the thread. So, both my statement in my original post and your
statement are a trifle careless. I'm glad to be corrected.
Your anonymous thread could be given a reference to a variable outside
of itself (in the enclosing class) which it could check periodically
to see if it should continue running.

Yes, but if the "anonymous" thread is given a reference, then
it's not anonymous.
Or, you could just hold on to a reference to your Timer object and
call its cancel method when/if you want to stop it:

Timer t = new Timer().schedule(

Your idea is correct, but the line above is not correct because
the types on the lhs and rhs of "=" are not compatible. One
would have to do something like I do below, which is correct
syntactically and semantically.
...

t.cancel();

Yes, that's a way to stop the thread and it's probably the best
way. I show the rewritten program below. Thanks for straight-
ening me out on the incompletness of my comment in the orig-
inal program. The rewritten program is below (but, of course,
the Timer thread is no longer anonymous).

George W. Cherry

import java.util.Timer;
import java.util.TimerTask;

public class AlarmClock {
public static void main(String[] args) {
int delay = Integer.parseInt( args[0] );
System.out.println(
"Setting alarm clock to go off " + delay + " seconds from now."
);
final Timer timer = new Timer();
timer.schedule(
new TimerTask() {
public void run() {
System.out.println("Ding-A-Ling! Time to get up!");
timer.cancel();
}
},
delay*1000
);
}//end main method
}//end AlarmClock class
 
D

Dave Glasser

Dave Glasser said:
I tend to use anonymous objects (and therefore anony-
mous threads) quite often. But how does one stop an
anonymous thread. In the following program I invoke
the garbage collector to stop the unreferenced Timer
thread?

How would you prefer to write this program?

George W. Cherry

import java.util.Timer;
import java.util.TimerTask;

public class AlarmClock {
public static void main(String[] args) {
int delay = Integer.parseInt( args[0] );
System.out.println(
"Setting alarm clock to go off " + delay + " seconds from now."
);
new Timer().schedule(
new TimerTask() {
public void run() {
System.out.println("Ding-A-Ling! Time to get up!");
}
},
delay*1000
);
System.gc(); //To shut down the anonymous Timer thread.
}//end main method
}//end AlarmClock class

First, invoking the garbage collector will not stop an anonymous
thread, nor will it arbitrarily stop any running thread; if it did
then Java would pretty worthless.

But "System.gc();" works! Run it and see. Then comment out
the invocation of the garbage collector, compile it, and run it;
and you'll see that the program "hangs".

Here's what the Javadoc for the Timer class says:

"After the last live reference to a Timer object goes away and all
outstanding tasks have completed execution, the timer's task execution
thread terminates gracefully (and becomes subject to garbage
collection). However, this can take arbitrarily long to occur. By
default, the task execution thread does not run as a daemon thread, so
it is capable of keeping an application from terminating. If a caller
wants to terminate a timer's task execution thread rapidly, the caller
should invoke the the timer's cancel method."

It's not "hung", so to speak; it's waiting for the Timer's thread to
terminate, which, as the Javadoc says, can take an "arbitrarily long"
time. I'll admit though that the difference between that and being
hung is subtle. :)

In all fairness to your
claim, Dave, an invocation of the gc on an anonymous thread
that HAS REACHED THE END of its run method will collect
the thread. So, both my statement in my original post and your
statement are a trifle careless. I'm glad to be corrected.

You're still being a trifle careless. You can't invoke gc() "on" a
particular thread. If a thread, or any object is eligible to be
garbage collected, it may be collected when you call gc(), and then
again, it may not be. It's just the luck of the draw that your call to
gc() causes your app to terminate. If it was a larger app that used
more memory, the effect might not be the same.
Yes, but if the "anonymous" thread is given a reference, then
it's not anonymous.

Sorry George, wrong again. In Java, the word "anonymous" describes a
class that has no name, not an object. And an instance of an anonymous
class can certainly have a reference, in fact most probably do. If I
do:

button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
...
}
});

I've just passed an instance of an anonymous class to a JButton's
addActionListener method. It's definitely an anonymous class, and the
JButton is definitely holding a (indirect) reference to the instance I
just passed it.
Your idea is correct, but the line above is not correct because
the types on the lhs and rhs of "=" are not compatible. One
would have to do something like I do below, which is correct
syntactically and semantically.
Oops!


Yes, that's a way to stop the thread and it's probably the best
way. I show the rewritten program below. Thanks for straight-
ening me out on the incompletness of my comment in the orig-
inal program. The rewritten program is below (but, of course,
the Timer thread is no longer anonymous).

It never was, George, as I explained above. :) The TimerTask, however,
was an instance of an anonymous class, because the subclass of
TimerClass you created had no name. The compiled class file for that
class is probably AlarmClock$1.class.
 
M

Mike Schilling

Dave Glasser said:
on Sat, 28 Jun 2003 02:13:02 GMT in comp.lang.java.programmer:
First, invoking the garbage collector will not stop an anonymous
thread, nor will it arbitrarily stop any running thread; if it did
then Java would pretty worthless.

Of course. What's happening here is that forcing a garbage collection is
causing the Timer to be collected. Its finalizer is recognizing that there
are no more tasks to be run and thus killing the thread. Since one can't
count on either:

A call to System.gc() collecting any particular object, or

Finalizers running promptly

this isn't a particularly good way to stop the thread.

The OP is correct that if you start a Thread and don't keep a reference to
it, you've lost control of it. Don't do that.
Your anonymous thread could be given a reference to a variable outside
of itself (in the enclosing class) which it could check periodically
to see if it should continue running.

Or, you could just hold on to a reference to your Timer object and
call its cancel method when/if you want to stop it:

Timer t = new Timer().schedule(
...

t.cancel();

Or you could tell the Timer to create a daemon thread:

new Timer(true)

which would allow the process to exit while the thread still lived.
 
D

Dave Glasser

2003 15:24:36 GMT in comp.lang.java.programmer:

Or you could tell the Timer to create a daemon thread:

new Timer(true)

which would allow the process to exit while the thread still lived.


I was thinking the same thing, but I tried it with George's example
program and the app exited immediately, before the TimerTask was
executed. When a Timer's thread is a daemon thread, the process will
exit regardless of any pending scheduled tasks there are. So if you're
going to make a Timer a daemon thread, you'd better rely on something
else to keep the app alive.
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top