Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 5
Most (if not all) JVM implementations use the underlying platform's threading capabilities. Because those capabilities are platform-specific, the order of your multithreaded programs' output might differ from the order of someone else's output. That difference results from scheduling, a topic I explore later in this series.
When you type java ThreadDemo to run the application, the JVM creates a starting thread of execution, which executes the main() method. By executing mt.start ();, the starting thread tells the JVM to create a second thread of execution that executes the byte code instructions comprising
the MyThread object's run() method. When the start() method returns, the starting thread executes its for loop to print a table of squares, while the new thread executes the run() method to print the right-angle triangle.
What does the output look like? Run ThreadDemo to find out. You will notice each thread's output tends to intersperse with the other's output. That results because both
threads send their output to the same standard output stream.
To grow proficient at writing multithreaded code, you must first understand the various methods that make up the Thread class. This section explores many of those methods. Specifically, you learn about methods for starting threads, naming threads,
putting threads to sleep, determining whether a thread is alive, joining one thread to another thread, and enumerating all
active threads in the current thread's thread group and subgroups. I also discuss Thread's debugging aids and user threads versus daemon threads.
I'll present the remainder of Thread's methods in subsequent articles, with the exception of Sun's deprecated methods.
Sun has deprecated a variety of Thread methods, such as suspend() and resume(), because they can lock up your programs or damage objects. As a result, you should not call them in your code. Consult the
SDK documentation for workarounds to those methods. I do not cover deprecated methods in this series.
Thread has eight constructors. The simplest are:
Thread(), which creates a Thread object with a default name
Thread(String name), which creates a Thread object with a name that the name argument specifies
The next simplest constructors are Thread(Runnable target) and Thread(Runnable target, String name). Apart from the Runnable parameters, those constructors are identical to the aforementioned constructors. The difference: The Runnable parameters identify objects outside Thread that provide the run() methods. (You learn about Runnable later in this article.) The final four constructors resemble Thread(String name), Thread(Runnable target), and Thread(Runnable target, String name); however, the final constructors also include a ThreadGroup argument for organizational purposes.
One of the final four constructors, Thread(ThreadGroup group, Runnable target, String name, long stackSize), is interesting in that it lets you specify the desired size of the thread's method-call stack. Being able to specify that
size proves helpful in programs with methods that utilize recursion—an execution technique whereby a method repeatedly calls
itself—to elegantly solve certain problems. By explicitly setting the stack size, you can sometimes prevent StackOverflowErrors. However, too large a size can result in OutOfMemoryErrors. Also, Sun regards the method-call stack's size as platform-dependent. Depending on the platform, the method-call stack's
size might change. Therefore, think carefully about the ramifications to your program before writing code that calls Thread(ThreadGroup group, Runnable target, String name, long stackSize).
Threads resemble vehicles: they move programs from start to finish. Thread and Thread subclass objects are not threads. Instead, they describe a thread's attributes, such as its name, and contain code (via a
run() method) that the thread executes. When the time comes for a new thread to execute run(), another thread calls the Thread's or its subclass object's start() method. For example, to start a second thread, the application's starting thread—which executes main()—calls start(). In response, the JVM's thread-handling code works with the platform to ensure the thread properly initializes and calls
a Thread's or its subclass object's run() method.
Once start() completes, multiple threads execute. Because we tend to think in a linear fashion, we often find it difficult to understand
the concurrent (simultaneous) activity that occurs when two or more threads are running. Therefore, you should examine a chart that shows
where a thread is executing (its position) versus time. The figure below presents such a chart.

The chart shows several significant time periods:
main()start()start() creates a new thread and returns to main()run()Note that the new thread's initialization, its execution of run(), and its termination happen simultaneously with the starting thread's execution. Also note that after a thread calls start(), subsequent calls to that method before the run() method exits cause start() to throw a java.lang.IllegalThreadStateException object.
During a debugging session, distinguishing one thread from another in a user-friendly fashion proves helpful. To differentiate
among threads, Java associates a name with a thread. That name defaults to Thread, a hyphen character, and a zero-based integer number. You can accept Java's default thread names or you can choose your own.
To accommodate custom names, Thread provides constructors that take name arguments and a setName(String name) method. Thread also provides a getName() method that returns the current name. Listing 2 demonstrates how to establish a custom name via the Thread(String name) constructor and retrieve the current name in the run() method by calling getName():
// NameThatThread.java
class NameThatThread
{
public static void main (String [] args)
{
MyThread mt;
if (args.length == 0)
mt = new MyThread ();
else
mt = new MyThread (args [0]);
mt.start ();
}
}
class MyThread extends Thread
{
MyThread ()
{
// The compiler creates the byte code equivalent of super ();
}
MyThread (String name)
{
super (name); // Pass name to Thread superclass
}
public void run ()
{
System.out.println ("My name is: " + getName ());
}
}
You can pass an optional name argument to MyThread on the command line. For example, java NameThatThread X establishes X as the thread's name. If you fail to specify a name, you'll see the following output: