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.