Threads are lightweight processes spun off from the main
process. We are all familiar with operating systems running separate
programs in parallel, or appearing that way, at least, on a single
processor system. These programs would be heavyweight processes
since they run in the local machine system. Threads are similar
except that they are parallel processes running inside of
a program.
So in Java you can create one or more threads within your program
just as you can run one or more programs in an operating system.
Most JVMs, in fact, take great advantage of threads.
In Java you create threads in two ways:
- A class extends the Thread
class and overrides it's run()
method.
- A class implements the Runnable
interface, which has one method: run().
The class passes a reference to itself when it creates a thread.
The thread then calls back to the run()
method in the class.
Here we discuss the two techniques:
Technque 1: Thread
Subclass
Creating a thread subclass offers the most conceptually
straightforward approach. The run()
method in the thread corresponds to the main()
method for an application. When the thread starts, it invokes
the method run()
and when the process returns from the run()
method, the thread dies.
Note: You cannot resurrect a dead
thread. You must instead create a new thread instance.
So in this approach the subclass must override the
run() method
where you put the code you wish to process in parallel to the main
program.
The Thread
subclass MyThread
overrides run(),
which has a loop that prints every 100 milliseconds for two seconds
(see Java Console for output):
|
public
class MyThread extends Thread {
public void run () {
int count = 0;
while (true) {
System.out.println ("Thread
1 alive");
// Print every 0.10sec
for 2 seconds
try {
Thread.sleep (100);
} catch (InterruptedException
e) {}
count++;
if (count >= 20) break;
}
System.out.println ("Thread stopping");
} // run
} // class MyThread |
MyClass1.java
- an application that runs MyThread.
|
The start()
method of MyApplet
class creates an instance of MyThread
and invokes the thread's start()
method. (Remember to differentiate between the start()
method in the Applet
class, called whenever the browser page opens, and the start()
in the Thread
class that initiates a thread.) This will in turn invoke the
run()
method, which the subclass has overridden.
|
/**
Demo of threading with a Thread subclass. **/
public class MyApplet extends java.applet.Applet
{
/** Applet's start method creates and starts
a thread.**/
public void start () {
// Create an instance of MyThread.
MyThread myThread = new MyThread
();
// Start the thread
myThread.start ();
}
public void paint(java.awt.Graphics g) {
g.drawString("Thread Demo 1",20,20);
}
} // class MyApplet |
MyClass2.java
- an application that implements Runnable.
|
The following diagram shows symbolically how the main
and thread processes run in parallel.
After the MyThread
is started, it will run in parallel with the original MyApplet
thread. By "run", we mean that the thread process executest
the run()
method until that method finishes and returns.
Technique 2:
Runnable Implementation
The second method is somewhat less straightforward
but is often convenient for cases where you want to create a single
type of thread, such as an animation in an applet.
In this case, you implement the Runnable
interface and override its run()
method. You pass a reference to an instance of that Runnable
implementation to a thread instance and the thread calls back
to the run()
method in the Runnable
object. The thread dies as in the previous method when the process
returns from run().
The program MyRunnableApplet
illustrates this approach. This class implements the Runnable
interface and its run()
method matches to that in the MyThread
class above.. Its constructor creates an instance of the Thread
class and passes a reference to itself (with the this
reference) in the thread's constructor. When the start()
method for the thread is invoked, the run()
in MyRunnableApplet
will be invoked. (See Java Console for output)
|
/**
Demo threading with Runnable implementation.**/
public class MyRunnableApplet extends java.applet.Applet
implements
Runnable {
/** Applet's start method creates a thread and
* lets it run for 2 secs. **/
public void start () {
// Create an instance of Thread with
a
// reference to this Runnable instance.
Thread thread = new Thread (this);
// Start the thread
thread.start ();
} // start
/** Override the Runnable run() method. **/
public void run() {
int count = 0;
while (true) {
System.out.println
("Thread 2 alive");
// Print every
0.10sec for 5 seconds
try{
Thread.sleep(100);
} catch (InterruptedException
e) {}
count++;
if ( count >= 20 ) break;
}
System.out.println ("Thread stopping");
} // run
public void paint(java.awt.Graphics g) {
g.drawString("Thread demo 2", 20,
20);
}
} // class MyRunnableApplet |
The following diagram shows schematically how this
approach works:
You see that the primary difference is that the thread invokes
the run()
method in the Runnable object rather that invoking its own run()
method.
Subclass vs. Runnable
So why two thread creation techniques? The choice between the two
methods depends on the particular application and what seems most
appropriate and convenient.
The Runnable
technique is particularly convenient when you want to create just
a single thread to carry out a specific task. The run()
method will have access to the instance variables in the Runnable
object. For example, a common approach to applet animation is to
make the applet Runnable.
The run()
method then has access to the applet's variables, which could be
parameters passed in the applet tags or set by the user via the
graphical interface.
Note also that since there are no restrictions on the number of
interfaces that a class can implement, it is easy to add Runnable
to a class.
On the other hand, if you want to create multiple threads, then
it usually makes more sense to use a Thread
subclass. This helps to better conceptualize the threads as independent
objects, each with its own independent sets of variables (as opposed
to sharing variables in the Runnable
object.) You can set the values of whatever parameters they need
via their constructors or "setter" methods.
References & Web Resources
Last update: Nov. 5, 2004
|