2.6 Threads and Objects
Let's talk a little more about
how
threads interact. Consider the
RandomCharacterGenerator thread. We saw how
another class (the SwingTypeTester class) kept a
reference to that thread and how it continued to call methods on that
object.
Although those methods are defined in the
RandomCharacterGenerator class, they are not
executed by that thread. Instead, methods like the setDone(
) method are executed by the Swing
event-dispatching
thread as it executes the actionPerformed()
method within the SwingTypeTester class. As far as
the virtual machine is concerned, the setDone()
method is just a series of statements; those statements do not
"belong" to any particular thread.
Therefore, the event-dispatching thread executes the
setDone() method in exactly the same way in which
it executes any other method.
This point is often confusing to developers who are new to threads;
it can be confusing as well to developers who understand threads but
are new to object-oriented programming. In Java, an instance of the
Thread class is just an object: it may be passed
to other methods, and any thread that has a reference to another
thread can execute any method of that other thread's
Thread object. The Thread
object is not the thread itself; it is instead a set of methods and
data that encapsulates information about the thread. And that method
and data can be accessed by any other thread.
For a more complex example, examine the
AnimatedCharacterCanvas class and determine how
many threads execute some of its methods. You should be comfortable
with the fact that four different threads use
this object. The RandomCharacterGenerator thread
invokes the newChar() method on that object. The
timing thread invokes the run() method. The
setDone() method is invoked by the Swing
event-dispatching thread. And the constructor of the class (i.e., the
default constructor) is invoked by the main method of the application
as it constructs the GUI.
The upshot of this is that you cannot look at any object source code
and know which thread is executing its methods or examining its data.
You may be tempted to look at a class or an object and wonder which
thread is running the code. The answer — even if the code is
with a class that extends the Thread class —
is that any of potentially thousands of threads could be executing
the code.
2.6.1 Determining the Current Thread
Sometimes, you need to find out what the current thread is. In the
most common case, code that belongs to an arbitrary object may need
to invoke a method of the thread class. In other circumstances, code
within a thread object may want to see if the code is being executed
by the thread represented by the object or by a completely different
thread.
You can retrieve a reference to the current thread by calling the
currentThread()
method (a static method of the
Thread class). Therefore, to see if code is being
executed by an arbitrary thread (as opposed to the thread represented
by the object), you can use this pattern:
public class MyThread extends Thread {
public void run( ) {
if (Thread.currentThread( ) != this)
throw new IllegalStateException(
"Run method called by incorrect thread");
... main logic ...
}
}
Similarly, within an arbitrary object, you can use the
currentThread() method to obtain a reference to a
current thread. This technique can be used by a
Runnable object to see whether it has been
interrupted:
public class MyRunnable implements Runnable {
public void run( ) {
while (!Thread.currentThread( ).isInterrupted( )) {
... main logic ...
}
}
}
In fact, the Thread class includes a static method
interrupted() that simply returns the value of
Thread.currentThread( ).isInterrupted(), but
you'll often see both uses within threaded programs.
In examples in later chapters, we use the currentThread() method to obtain a thread reference in order to invoke other
methods of the Thread class that we
haven't yet examined.
|