BBS水木清华站∶精华区
发信人: abcd12 (Forgiven Not Forgoten), 信区: Java
标 题: java thread programming
发信站: BBS 水木清华站 (Sun Aug 13 22:46:07 2000)
This chapter shows just how simple it is to get a new thread up and running
in a tiny Java application. The first thread is the "main" thread that is a
lways spawned by the Java Virtual Machine (JavaVM) and starts an application
. This main thread then spawns the second thread. Each of these threads will
print its messages to the console to demonstrate that they both appear to b
e running simultaneously.
The steps to spawn a new thread in this chapter's example are
Extend the java.lang.Thread class.
Override the run() method in this subclass of Thread.
Create an instance of this new class.
Invoke the start() method on the instance.
Extending the java.lang.Thread Class
An instance of the java.lang.Thread class is associated with each thread run
ning in the JavaVM. These Thread objects serve as the interface for interact
ing with the underlying operating system thread. Through the methods in this
class, threads can be started, stopped, interrupted, named, prioritized, an
d queried regarding their current state.
----------------------------------------------------------------------------
----
NOTE: There are two ways to create a new class that can have a thread runnin
g within it. One way is to extend the Thread class. The other is to extend a
ny class and implement the Runnable interface. For the sake of illustration,
extending Thread is the simplest approach and is initially used in this boo
k. Implementing the Runnable interface tends to work much better in the real
world; this technique is introduced in Chapter 4, "Implementing Runnable Ve
rsus Extending Thread."
----------------------------------------------------------------------------
----
In this example, the first step towards spawning a new thread is to extend t
he java.lang.Thread class:
public class TwoThread extends Thread {
// ...
}
The subclass TwoThread IS-A Thread and consequently inherited the protected
and public members from its superclass. TwoThread can be started, stopped, i
nterrupted, named, prioritized, and queried regarding its current state, in
addition to all the other behaviors added to the extended class. Figure 2.1
shows the class diagram for TwoThread.
FIGURE 2.1 The class diagram for TwoThread.
----------------------------------------------------------------------------
----
NOTE: In this book, the notation used for class relationships is closely bas
ed on the Unified Modeling Language (UML). Figure 2.2 shows an example of re
lationships.
----------------------------------------------------------------------------
----
FIGURE 2.2 A sample class diagram showing generic relationships.
----------------------------------------------------------------------------
----
NOTE: Different terms are used in this book to describe interclass relations
hips. All the following phrases are true about the relationships depicted in
Figure 2.2:
ClassA is the superclass of ClassB.
ClassB is a subclass of ClassA.
ClassB extends ClassA.
ClassB IS-A ClassA.
ClassB implements InterfaceF.
ClassB IS-A InterfaceF.
ClassB is the superclass of ClassC and ClassD.
ClassC is a subclass of both ClassB and ClassA.
ClassC IS-A ClassB, ClassC IS-A ClassA, and ClassC IS-A InterfaceF.
ClassE contains (at least one reference to) ClassB.
ClassE HAS-A ClassB reference within it.
----------------------------------------------------------------------------
----
Overriding the run() Method
After extending Thread, the next step is to override the run() method becaus
e the run() method of Thread does nothing:
public void run() { }
When a new thread is started, the entry point into the program is the run()
method. The first statement in run() will be the first statement executed by
the new thread. Every statement that the thread will execute is included in
the run() method or is in other methods invoked directly or indirectly by r
un(). The new thread is considered to be alive from just before run() is cal
led until just after run() returns, at which time the thread dies. After a t
hread has died, it cannot be restarted.
In this chapter's example, run() is overridden with code to loop for 10 iter
ations and print the message New thread each time through:
public void run() {
for ( int i = 0; i < 10; i++ ) {
System.out.println("New thread");
}
}
After the for loop completes, the thread returns from the run() method and q
uietly dies.
Spawning a New Thread
New threads are spawned from threads that are already running. First, a new
Thread instance must be constructed. In this example, a new TwoThread object
will work just fine because TwoThread IS-A Thread:
TwoThread tt = new TwoThread();
The next step is to kick off the execution of the thread by invoking the sta
rt() method on the TwoThread object ( start() is inherited from Thread):
tt.start();
A call to start() returns right away and does not wait for the other thread
to begin execution. In start(), the parent thread asynchronously signals thr
ough the JavaVM that the other thread should be started as soon as it's conv
enient for the thread scheduler. At some unpredictable time in the very near
future, the other thread will come alive and invoke the run() method of the
Thread object (or in this case, the overridden run() method implemented in
TwoThread). Meanwhile, the original thread is free to continue executing the
statements that follow the start() call.
The two threads run concurrently and independently. On a multi-processor mac
hine, these two threads may actually be running at the very same instant , e
ach on its own processor. This true simultaneity would also have to be suppo
rted in the port of the JavaVM for that platform in order to exploit multipl
e processors.
A more likely case is that only a single processor is present. The JavaVM an
d the operating system work together to schedule each thread for short, inte
rleaved bursts of processor usage. Each thread takes a turn running while th
e other threads are frozen, waiting for their next turn on the processor. Th
is context switching among threads generally occurs very quickly and gives t
he illusion of truly simultaneous execution.
----------------------------------------------------------------------------
----
CAUTION: A newly created thread may start executing (enter the run() method)
at any time after start() is invoked. This means that the original thread m
ight be swapped out before any statement that follows start() is executed.
If the original thread is executing this code:
stmt1();
tt.start();
stmt2();
and the new thread has a run() method such as this:
public void run() {
stmtA();
stmtB();
}
the order of actual statement execution in the processor might be stmt1(), t
t.start(), stmt2(), stmtA(), and stmtB(). Alternatively, it might be stmt1()
, tt.start(), stmtA(), stmtB(), and stmt2(). Perhaps, it might be one of the
other permutations!
Important to note is that although the order in which each thread will execu
te its own statements is known and straightforward, the order in which the s
tatements will actually be run on the processor is indeterminate, and no par
ticular order should be counted on for program correctness.
----------------------------------------------------------------------------
----
Putting It All Together
Combining the preceding code and adding a second 10-iteration loop for the m
ain thread to run produces the complete code for TwoThread.java, shown in Li
sting 2.1.
Listing 2.1 TwoThread.java--The Complete Code for the TwoThread Example
1: public class TwoThread extends Thread {
2: public void run() {
3: for ( int i = 0; i < 10; i++ ) {
4: System.out.println("New thread");
5: }
6: }
7:
8: public static void main(String[] args) {
9: TwoThread tt = new TwoThread();
10: tt.start();
11:
12: for ( int i = 0; i < 10; i++ ) {
13: System.out.println("Main thread");
14: }
15: }
16: }
First, note that the new class TwoThread directly extends Thread, so it IS-A
Thread and takes on all the capabilities of its superclass.
Application execution begins with the main thread, which is spawned by the J
avaVM for all applications at startup, entering the main method (line 8). It
proceeds to create a new TwoThread instance (line 9). Next, it spawns a new
thread of execution by invoking the start() method (line 10). This new thre
ad will begin its execution by invoking the run() method (line 2) of TwoThre
ad.
At this point, two threads are ready to run, and the thread scheduler runs e
ach for short periods, alternating between them. If this switching back and
forth is fast enough, they appear to be running simultaneously.
After the main thread spawns the new thread, the main thread proceeds into i
ts loop (lines 12-14) and prints Main thread to the console 10 times. When i
t is done with the loop, it falls through and returns from main(). The main
thread dies when it returns from main().
At approximately the same time, the new thread enters the run() method (line
2), proceeds into its loop (lines 3-5), and prints New thread to the consol
e 10 times. When it is done with the loop, it falls through and returns from
run(). The new thread dies when it returns from run().
When both threads have completed their work and died, the JavaVM shuts down
and the application is done.
Listing 2.2 shows possible output from running this application (your output
might differ). During this run of the application, the messages from the tw
o threads happened to be perfectly interleaved, starting with the message fr
om the main thread. There is no guarantee that this output would be the same
if the application was run again. Thread scheduling is nondeterministic and
depends on many factors, including what else is currently running in the op
erating system. The thread scheduler makes what seem to be random decisions
about how long each thread should be allowed to run between context switches
. The only thing that can be counted on from running this application is tha
t each message will print exactly 10 times, regardless of the order of the m
essages.
Listing 2.2 Possible Output from a Run of TwoThread.java
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Main thread
New thread
Summary
This chapter explores how to create a new thread by performing these tasks:
Subclassing Thread
Overriding the run() method of Thread to specify the statements to be execut
ed by the new thread
Creating a new instance of this subclass of Thread
Spawning a new thread by invoking start() on this instance
That's all there is to getting a second thread up and running in Java! The f
ollowing chapters explore the complexities of threads and the coordination o
f the intercommunication that usually must occur among them.
--
WE DON'T KNOW WHO WE ARE UNTIL WE SEE WHAT WE DO!
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.204.9.81]
BBS水木清华站∶精华区