| ## Java 1.1 Unleashed # - 6 - Threads and Multithreading by Eric Williams IN THIS CHAPTER Multithreading Concurrency Advanced Monitor Concepts Synchronization ## Multithreading One of the characteristics that makes Java a powerful programming language is its support for multithreaded programming as an integrated part of the language. This provision is unique because most modern programming languages either do not offer multithreading or provide multithreading as a nonintegrated package. Java, however, offers a single, integrated view of multithreading. Multithreaded programming is an essential aspect of programming in Java. To master the Java programming language, you should first become familiar with the concepts of multithreaded programming. Then you should learn how multithreaded and concurrent programming are done in Java. This chapter presents a complete introduction and reference to Java threads, including these topics: How to write and start your own threads A comprehensive reference to the `Thread` and `ThreadGroup` classes How to make your classes thread safe An introduction to Java monitors How to coordinate the actions of multiple threads NOTE: Multithreading and concurrent programming are unfamiliar concepts for most new Java programmers. If you are familiar with only single-threaded languages like Visual Basic, Delphi, Pascal, Cobol, and so on, you may be worried that threads are too hard to learn. Although learning to use Java threads is not trivial, the model is simple and easy to understand. Threads are a normal everyday aspect of developing Java applications and applets. ### What Is a Thread? In the early days of computing, computers were single tasking--that is, they ran a single job at a time. The big, lumbering machine would start one job, run that job to completion, then start the next job, and so on. When engineers became overly frustrated with these batch-oriented systems, they rewrote the programs that ran the machines and thus was born the modern multitasking operating system. Multitasking refers to a computer's capability to perform multiple jobs concurrently. For the most part, modern operating systems like Windows 95 or Solaris can run two or more programs at the same time. While you are using Netscape to download a big file, you can be running Solitaire in a different window; both programs are running at the same time. Multithreading is an extension of the multitasking paradigm. But rather than multiple programs, multithreading involves multiple threads of control within a single program. Not only is the operating system running multiple programs, each program can run multiple threads of control--think of threads as subprograms--within the program. For example, using a Web browser, you can print one Web page, download another, and fill out a form in a third--all at the same time. A thread is a single sequence of execution within a program. Until now, you have probably used Java to write single-threaded applications, something like this:
    class MainIsRunInAThread {
        public static void main(String[] args) {
            // main() is run in a single thread
            System.out.println(Thread.currentThread());
            for (int i=0; i<1000; i++) {
                System.out.println("i == " + i);
            }
        }

    }
This example is simplistic, but it demonstrates the use of a single Java thread. When a Java application begins, the virtual machine (VM) runs the `main()` method inside a Java thread. (You have already used Java threads and didn't even know it!) Within this single thread, this simple application's `main()` method counts from 0 to 999, printing out each value as it is counted. Programming within a single sequence of control can limit your ability to produce usable Java software. (Imagine using an operating system that could execute only one program at a time, or a Web browser that could load only a single page at a time.) When you write a program, you often want the program to do multiple things at the same time. For example, you may want the program to retrieve an image over the network at the same time it is requesting an updated stock report and also running several animations--and you want all this to occur concurrently. This is the kind of situation in which Java threads become useful. Java threads allow you to write programs that do many things at once. Each thread represents an independently executing sequence of control. One thread can write a file out to disk while a different thread responds to user keystroke events. Before jumping into the details about Java threads, let's take a peek at what a multithreaded application looks like. Listing 6.1 modifies the preceding single-threaded application to take advantage of threads. Instead of counting from 0 to 999 in one thread, this application uses five different threads to count from 0 to 999--each thread counts 200 numbers: 0 to 199, 200 to 399, and so on. Don't worry if you don't understand the details of this example yet; it is presented only to introduce you to threads. #### Listing 6.1. A simple multithreaded application.
    class CountThreadTest extends Thread {
        int from, to;
        public CountThreadTest(int from, int to) {
            this.from = from;
            this.to = to;
        }
        // the run() method is like main() for a thread
        public void run() {
            for (int i=from; i<to; i++) {
                System.out.println("i == " + i);
            }
        }
        public static void main(String[] args) {
            // spawn 5 threads, each of wich counts 200 numbers
            for (int i=0; i<5; i++) {
                CountThreadTest t = new CountThreadTest(i*200, (i+1)*200);
                // starting a thread will launch a separate sequence
                // of control and execute the run() method of the thread
                t.start();
            }
        }
    }
When this application starts, the VM invokes the `main()` method in its own thread. `main()` then starts five separate threads to perform the counting operations. Figure 6.1 shows the threads in the `CountThreadTest` application. Figure 6.1. Parallel Java threads. NOTE: Even though multiple threads may appear to perform tasks at the same time, technically speaking, this may not be true. Even today, most computers are equipped with a single processor--such computers can perform at most one task at a time. On single-processor systems, the operating system continuously switches between different tasks and threads, allowing each active task or thread to use the CPU for a small amount of time. This subject is discussed in detail in "Thread Scheduling," later in this chapter. ### Java Threads Support for multiple threads of execution is not a Java invention. Threads have been around for a long time and have been implemented in many programming languages. However, programmers have had to struggle with a lack of thread standards. Different platforms have different thread packages, each with a different API. Operating systems do not have uniform support for threads; some support threads in the OS kernel, and some do not. Only recently has a standard emerged for threads--POSIX threads (IEEE standard 1003.1c-1995). However, the POSIX threads standard defines only a C programming interface (not a Java interface) and is not yet widely implemented. One of the greatest benefits of Java is that it presents the Java programmer with a unified multithreading API--one that is supported by all Java virtual machines on all platforms. When you use Java threads, you do not have to worry about which threading packages are available on the underlying platform or whether the operating system supports kernel threads. The virtual machine isolates you from the platform-specific threading details. The Java threading API is identical on all Java implementations. ### Creating New Threads The first thing you need to know about threads is how to create and run a thread. This process involves two steps: writing the code that is executed in the thread and writing the code that starts the thread. As discussed earlier, you are already familiar with how to write single-threaded programs. When you write a `main()` function, that method is executed in a single thread. The Java virtual machine provides a multithreaded environment, but it starts user applications by calling `main()` in a single thread. An application's `main()` method provides the central logic for the main thread of the application. Writing the code for a thread is similar to writing `main()`. You must provide a method that implements the main logic of the thread. This method is always named `run()` and has the following signature: `public void run();``` Notice that the `run()` method is not a static method as `main()` is. The `main()` method is static because an application starts with only one `main()` method. But an application may have many threads, so the main logic for a thread is associated with an object--the `Thread` object. You can provide an implementation for the `run()` method in two ways. Java supports the `run()` method in subclasses of the `Thread` class. Java also supports `run()` through the `Runnable` interface. Both methods for providing a `run()` method implementation are described in the following sections. #### Subclassing the Thread Class This section discusses how to create a new thread by subclassing `java.lang.Thread`. Let's start with a plausible situation in which a thread might be useful. Suppose that you are building an application; in one part of this application, a file must be copied from one directory to a different directory. But when you run the application, you find that if the file is large, the application stalls during the time that the file is being copied. You determine that the cause of the stall is this: When the application is copying the file, it is unable to respond to user-interface events. To improve this situation, you decide that the file-copy operation should be performed concurrently, in a separate thread. To move this logic to a thread, you provide a subclass of the `Thread` class that contains this logic, implemented in the `run()` method. The `FileCopyThread` class shown in Listing 6.2 contains this logic. #### Listing 6.2. The file-copy logic in FileCopyThread.
    // subclass from Thread to provide your own kind of Thread
    class FileCopyThread extends Thread {
        private File from;
        private File to;
        public FileCopyThread(File from, File to) {
            this.from = from;
            this.to = to;
        }
        // implement the main logic of the thread in the run()
        // method [run() is equivalent to an application's main()]
        public void run() {
            FileInputStream in = null;
            FileOutputStream out = null;
            byte[] buffer = new byte[512];
            int size = 0;
            try {
                // open the input and output streams
                in = new FileInputStream(from);
                out = new FileOutputStream(to);
                // copy 512 bytes at a time until EOF
                while ((size = in.read(buffer)) != -1) {
                   out.write(buffer, 0, size);
                }
            } catch(IOException ex) {
                ex.printStackTrace();
            } finally {
                // close the input and output streams
                try {
                    if (in != null) { in.close(); }
                    if (out != null) { out.close(); }
                } catch (IOException ex) {
                }
            }
        }

    }
Let's analyze the `FileCopyThread` class. Note that the `FileCopyThread` subclasses from `Thread`. By subclassing from `Thread`, `FileCopyThread` inherits all the state and behavior of a `Thread`--the property of "being a thread." The `FileCopyThread` class implements the main logic of the thread in the `run()` method. (Remember that the `run()` method is the initial method for a Java thread, just as the `main()` method is the initial method for a Java application.) Within `run()`, the input file is copied to the output file in 512-byte chunks. When a `FileCopyThread` instance is created and started, the entire `run()` method is executed in one separate sequence of control (you'll see how this is done soon). Now that you are familiar with how to write a `Thread` subclass, you have to learn how to use that class as a separate control sequence within a program. To use a thread, you must start the concurrent execution of the thread by calling the `Thread` object's `start()` method. The following code demonstrates how to launch a file-copy operation as a separate thread:
    File from = getCopyFrom();
    File to = getCopyTo();
    // create an instance of the thread class
    Thread t = new FileCopyThread(from, to);
    // call start() to activate the thread asynchronously
    t.start();
Invoking the `start()` method of a `FileCopyThread` object begins the concurrent execution of that thread. When the thread starts running, its `run()` method is called. In this case, the file copy begins its execution concurrently with the original thread. When the file copy is finished, the `run()` method returns (and the concurrent execution of the thread ends). This process is shown in Figure 6.2. Figure 6.2. Concurrent file copy. #### Implementing the Runnable Interface There are situations in which it is not convenient to create a `Thread` subclass. For example, you may want to add a `run()` method to a preexisting class that does not inherit from `Thread`. The Java `Runnable` interface makes this possible. The Java threading API supports the notion of a thread-like entity that is an interface: `java.lang.Runnable`. `Runnable` is a simple interface, with only one method:
    public interface Runnable {
        public void run();
    }
This interface should look familiar. In the previous section, we covered the `Thread` class, which also supported the `run()` method. To subclass `Thread`, we redefined the `Thread` `run()` method. To use the `Runnable` interface, you must write a `run()` method and add the text `implements Runnable` to the class. Reimplementing the `FileCopyThread` (of the previous example) as a `Runnable` interface requires few changes:
    // implementing Runnable is a different way to use threads
    class FileCopyRunnable implements Runnable {
        // the rest of the class remains mostly the same
        ...
    }
To use a `Runnable` interface as a separate control sequence requires the cooperation of a `Thread` object. Although the `Runnable` object contains the main logic, `Thread` is the only class that encapsulates the mechanism of launching and controlling a thread. To support `Runnable`, a separate `Runnable` parameter was added to several of the `Thread` class constructors. A thread that has been initialized with a `Runnable` object will call that object's `run()` method when the thread begins executing. Here is an example of how to start a thread using `FileCopyRunnable`:
    File from = new File("file.1");
    File to = new File("file.2");
    // create an instance of the Runnable
    Runnable r = new FileCopyRunnable(from, to);
    // create an instance of Thread, passing it the Runnable
    Thread t = new Thread(r);
    // start the thread
    t.start();
### Thread States Although you have learned a few things about threads, we have not yet discussed one aspect that is critical to your understanding of how threads work in Java--thread states. A Java thread, represented by a `Thread` object, traverses a fixed set of states during its lifetime (see Figure 6.3). Figure 6.3. Thread states. When a `Thread` object is first created, it is in the `NEW` state. At this point, the thread is not executing. When you invoke the `Thread`'s `start()` method, the thread changes to the `RUNNABLE` state. When a Java thread is `RUNNABLE`, it is eligible for execution. However, a thread that is `RUNNABLE` is not necessarily running. `RUNNABLE` implies that the thread is alive and that it can be allocated CPU time by the system when the CPU is available--but the CPU may not always be available. On single-processor systems, Java threads must share the single CPU; additionally, the Java virtual machine task (or process) must also share the CPU with other tasks running on the system. How a thread is allocated CPU time is covered in greater depth in "Scheduling and Priority," later in the chapter. When certain events happen to a `RUNNABLE` thread, the thread may enter the `NOT RUNNABLE` state. When a thread is `NOT RUNNABLE`, it is still alive, but it is not eligible for execution. The thread is not allocated time on the CPU. Some of the events that may cause a thread to become `NOT RUNNABLE` include the following: The thread is waiting for an I/O operation to complete The thread has been put to sleep for a certain period of time (using the `sleep()` method) The `wait()` method has been called (as discussed in "Synchronization," later in this chapter) The thread has been suspended (using the `suspend()` method) A `NOT RUNNABLE` thread becomes `RUNNABLE` again when the condition that caused the thread to become `NOT RUNNABLE` ends (I/O has completed, the thread has ended its `sleep()` period, and so on). During the lifetime of a thread, the thread may frequently move between the `RUNNABLE` and `NOT RUNNABLE` states. When a thread terminates, it is said to be `DEAD`. Threads can become `DEAD` in a variety of ways. Usually, a thread dies when its `run()` method returns. A thread may also die when its `stop()` or `destroy()` method is called. A thread that is `DEAD` is permanently `DEAD`--there is no way to resurrect a `DEAD` thread. NOTE: When a thread dies, all the resources consumed by the thread--including the `Thread` object itself--become eligible for reclamation by the garbage collector (if, of course, they are not referenced elsewhere). Programmers are responsible for cleaning up system resources (closing open files, disposing of graphics contexts, and so on) while a thread is terminating, but no cleanup is required after a thread dies. ### The Thread API The following sections present a detailed analysis of the Java `Thread` API. #### Constructors The `Thread` class has seven different constructors:
    public Thread();
    public Thread(Runnable target);
    public Thread(Runnable target, String name);
    public Thread(String name);
    public Thread(ThreadGroup group, Runnable target);
    public Thread(ThreadGroup group, Runnable target, String name);
    public Thread(ThreadGroup group, String name);
These constructors represent most of the combinations of three different parameters: thread name, thread group, and a `Runnable` target object. To understand the constructors, you must understand the three parameters: `name` is the (string) name to be assigned to the thread. If you fail to specify a name, the system generates a unique name of the form `Thread-N`, where `N` is a unique integer. `target` is the `Runnable` instance whose `run()` method is executed as the main method of the thread. `group` is the `ThreadGroup` to which this thread will be added. (The `ThreadGroup` class is discussed in detail later in this chapter.) Constructing a new thread does not begin the execution of that thread. To launch the `Thread` object, you must invoke its `start()` method. When creating a thread, the priority and daemon status of the new thread are set to the same values as the thread from which the new thread was created. CAUTION: Although it is possible to allocate a thread using `new Thread()`, it is not useful to do so. When constructing a thread directly (without subclassing), the `Thread` object requires a target `Runnable` object because the `Thread` class itself does not contain your application's logic. #### Naming `public final String getName();` `public final void setName(String name);` Every Java thread has a name. The name can be set during construction or with the `setName()` method. If you fail to specify a name during construction, the system generates a unique name of the form `Thread-N`, where `N` is a unique integer; the name can be changed later using `setName()`. The name of a thread can be retrieved using the `getName()` method. Thread names are important because they provide the programmer with a useful way to identify particular threads during debugging. You should name a thread in such a way that you (or others) will find the name helpful in identifying the purpose or function of the thread during debugging. #### Starting and Stopping To start and stop threads once you have created them, you need the following methods:
    public void start();
    public final void stop();
    public final void stop(Throwable obj);
    public void destroy();
To begin a new thread, create a new `Thread` object and call its `start()` method. An exception is thrown if `start()` is called more than once on the same thread. As discussed in "Thread States," earlier in this chapter, there are two main ways a thread can terminate: The thread can return from its `run()` method, ending gracefully. Or the thread can be terminated by the `stop()` or `destroy()` method. When invoked on a thread, the `stop()` method causes that thread to terminate by throwing an exception to the thread (a `ThreadDeath` exception). Calling `stop()` on a thread has the same behavior as executing `throw new ThreadDeath()` within the thread, except that `stop()` can also be called from other threads (whereas the `throw` statement affects only the current thread). To understand why `stop()` is implemented this way, consider what it means to stop a running thread. Active threads are part of a running program, and each runnable thread is in the middle of doing something. It is likely that each thread is consuming system resources: file descriptors, graphics contexts, monitors (to be discussed later), and so on. If stopping a thread caused all activity on the thread to cease immediately, these resources might not be cleaned up properly. The thread would not have a chance to close its open files or release the monitors it has locked. If a thread were stopped at the wrong moment, it would be unable to free these resources; this leads to potential problems for the virtual machine (running out of open file descriptors, for example). To provide for clean thread shutdown, the thread to be stopped is given an opportunity to clean up its resources. A `ThreadDeath` exception is thrown to the thread, which percolates up the thread's stack and through the exception handlers that are currently on the stack (including `finally` blocks). Monitors are also released by this stack-unwinding process. Listing 6.3 shows how calling `stop()` on a running thread generates a `ThreadDeath` exception. #### Listing 6.3. Generating a ThreadDeath exception with stop().
    class DyingThread extends Thread {
        // main(), this class is an application
        public static void main(String[] args) {
            Thread t = new DyingThread();          // create the thread
            t.start();                             // start the thread
            // wait for a while
            try { Thread.sleep(100); } catch (InterruptedException e) { }
            t.stop();                              // now stop the thread
        }
        // run(), this class is also a Thread
        public void run() {
            int n = 0;
            PrintStream ps = null;
            try {
                ps = new PrintStream(new FileOutputStream("big.txt"));
                while (true) {                           // forever
                    ps.println("n == " + n++);
                    try { Thread.sleep(5); } catch (InterruptedException e) { }
                }
            } catch (ThreadDeath td) {                 // watch for the stop()
                System.out.println("Cleaning up.");
                ps.close();                            // close the open file
                // it is very important to rethrow the ThreadDeath
                throw td;
            } catch (IOException e) {
            }
        }

    }
The `DyingThread` class has two parts. The `main()` method spawns a new `DyingThread`, waits for a period of time, and then sends a `stop()` to the thread. The `DyingThread` `run()` method, which is executed in the spawned thread, opens a file and periodically writes output to that file. When the thread receives the `stop()`, it catches the `ThreadDeath` exception and closes the open file. It then rethrows the `ThreadDeath` exception. When you run the code shown in Listing 6.3, you see the following output: `Cleaning up.` NOTE: Java provides a convenient mechanism for programmers to write "cleanup" code--code that is executed when errors occur or when a program or thread terminates. (Cleanup involves closing open files, disposing of graphics contexts, hiding windows, and so on.) Exception handler `catch` and `finally` blocks are good locations for cleanup code. Programmers use a variety of styles to write cleanup code. Some programmers place cleanup code in `catch(ThreadDeath td)` exception handlers (as was done in Listing 6.3). Others prefer to use `catch(Throwable t)` exception handlers. Both these methods are good, but writing cleanup code in a `finally` block is the best solution for most situations. A `finally` block is executed unconditionally, whether the exception handler exited because of a thrown exception or not. If an exception was thrown, it is automatically rethrown after the `finally` block has completed. Although the `ThreadDeath` solution allows the application a high degree of flexibility, there are problems. By catching the `ThreadDeath` exception, a thread can actually prevent `stop()` from having the desired effect. The code to do this is trivial:
    // prevent stop() from working
    catch (ThreadDeath td) {
        System.err.println("Just try to stop me. I'm invincible.");
        // oh no, I've failed to rethrow td
    }
Calling `stop()` is not sufficient to guarantee that a thread will end. This is a serious problem for Java-enabled Web browsers; there is no guarantee that an applet will terminate when `stop()` is invoked on a thread belonging to the applet. The `destroy()` method is stronger than the `stop()` method. The `destroy()` method is designed to terminate the thread without resorting to the `ThreadDeath` mechanism. The `destroy()` method stops the thread immediately, without cleanup; any resources held by the thread are not released. CAUTION: The `destroy()` method is not implemented in the Java Development Kit, in all versions up to and including 1.1. Calling this method results in a `NoSuchMethodError` exception. Although there has been no comment about when this method will be implemented, it is likely that it will not become available until JavaSoft can implement it in a way that cleans up the dying thread's environment (locked monitors, pending I/O, and so on). #### Scheduling and Priority Thread scheduling is defined as the mechanism used to determine how `RUNNABLE` threads are allocated CPU time (that is, when they actually get to execute for a period of time on the computer's CPU). In general, scheduling is a complex subject that uses terms such as pre- emptive, round-robin scheduling, priority-based scheduling, time-sliced, and so on. A thread-scheduling mechanism is either preemptive or nonpreemptive. With preemptive scheduling, the thread scheduler preempts (pauses) a running thread to allow different threads to execute. A nonpreemptive scheduler never interrupts a running thread; instead, the nonpreemptive scheduler relies on the running thread to yield control of the CPU so that other threads can execute. Under nonpreemptive scheduling, other threads may starve (never get CPU time) if the running thread fails to yield. Among thread schedulers classified as preemptive, there is a further classification. A pre- emptive scheduler can be either time-sliced or nontime-sliced. With time-sliced scheduling, the scheduler allocates a period of time for which each thread can use the CPU; when that amount of time has elapsed, the scheduler preempts the thread and switches to a different thread. A nontime-sliced scheduler does not use elapsed time to determine when to preempt a thread; it uses other criteria such as priority or I/O status. Different operating systems and thread packages implement a variety of scheduling policies. But Java is intended to be platform independent. The correctness of a Java program should not depend on what platform the program is running on, so the designers of Java decided to isolate the programmer from most platform dependencies by providing a single guarantee about thread scheduling: The highest priority `RUNNABLE` thread is always selected for execution above lower priority threads. (When multiple threads have equally high priorities, only one of those threads is guaranteed to be executing.) Java threads are guaranteed to be preemptive, but not time sliced. If a higher priority thread (higher than the current thread) becomes `RUNNABLE`, the scheduler preempts the current thread. However, if an equal or lower priority thread becomes `RUNNABLE`, there is no guarantee that the new thread will ever be allocated CPU time until it becomes the highest priority `RUNNABLE` thread. NOTE: The current implementation of the Java VM uses different thread packages on different platforms; thus, the behavior of the Java thread scheduler varies slightly from platform to platform. It is best to check with your Java VM supplier to determine whether the VM uses native threads and whether the platform's native threads are time sliced (some native threading packages, most notably Solaris threads, are not time sliced). Even though Java threads are not guaranteed to be time sliced, this should not be a problem for the majority of Java applications and applets. Java threads release control of the CPU when they become `NOT RUNNABLE`. If a thread is waiting for I/O, is sleeping, or is waiting to enter a monitor, the thread scheduler will select a different thread for execution. Generally, only threads that perform intensive numerical analysis (without I/O) will be a problem. A thread would have to be coded like the following example to prevent other threads from running (and such a thread would starve other threads only on some platforms--on Windows NT, for example, other threads would still be allowed to run): `int i = 0; while (true) { i++; }` There are a variety of techniques you can implement to prevent one thread from consuming too much CPU time: Don't write code such as `while (true) { }`. It is acceptable to have infinite loops--as long as what takes place inside the loop involves I/O, `sleep()`, or interthread coordination (using the `wait()` and `notify()` methods, discussed later in this chapter). Occasionally call `Thread.yield()` when performing operations that are CPU intensive. The `yield()` method allows the scheduler to spend time executing other threads. Lower the priority of CPU-intensive threads. Threads with a lower priority run only when the higher priority threads have nothing to do. For example, the Java garbage collector thread is a low priority thread. Garbage collection takes place when there are no higher priority threads that need the CPU; this way, garbage collection does not needlessly stall the system. By using these techniques, your applications and applets will be well behaved on any Java platform. ### Setting Thread Priority
    public final static int MAX_PRIORITY = 10;
    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final int getPriority();
    public final void setPriority(int newPriority);
Every thread has a priority. When a thread is created, it inherits the priority of the thread that created it. The priority can be adjusted subsequently using the `setPriority()` method. The priority of a thread can be obtained using `getPriority()`. There are three symbolic constants defined in the `Thread` class that represent the range of priority values: `MIN_PRIORITY`, `NORM_PRIORITY`, and `MAX_PRIORITY`. The priority values range from `1` to `10`, in increasing priority. An exception is thrown if you attempt to set priority values outside this range. ### Waking Up a Thread
    public void interrupt();
    public static boolean interrupted();
    public boolean isInterrupted();
To send a wake-up message to a thread, call `interrupt()` on its `Thread` object. Calling `interrupt()` causes an `InterruptedException` to be thrown in the thread and sets a flag that can be checked by the running thread using the `interrupted()` or `isInterrupted()` method. Calling `Thread.interrupted()` checks the interrupt status of the current thread and resets the interrupt status to `false` (in versions before 1.1, the interrupt status is not reset). Calling `isInterrupted()` on a `Thread` object (which can be other than the current thread) checks the interrupt status of that thread but does not change the status. The `interrupt()` method is useful in waking a thread from a blocking operation such as I/O, `wait()`, or an attempt to enter a `synchronized` method. CAUTION: The `interrupt()` method is not fully implemented in the JDK 1.0.x. Calling `interrupt()` on a thread sets the `interrupted` flag but does not throw an `InterruptedException` or end a blocking operation in the target thread; threads must check `interrupted()` to determine whether the thread has been interrupted. The `interrupt()` method is fully implemented in the Java virtual machine, version 1.1. ### Suspending and Resuming Thread Execution
    public final void suspend();
    public final void resume();
Sometimes, it is necessary to pause a running thread. You can do so using the `suspend()` method. Calling the `suspend()` method ensures that a thread will not be run. The `resume()` method reverses the `suspend()` operation. A call to `suspend()` puts the thread in the `NOT RUNNABLE` state. However, calling `resume()` does not guarantee that the target thread will become `RUNNABLE`; other events may have caused the thread to be `NOT RUNNABLE` (or `DEAD`). ### Putting a Thread to Sleep
    public static void sleep(long millisecond);
    public static void sleep(long millisecond, int nanosecond);
To pause the current thread for a specified period of time, call one of the varieties of the `sleep()` method. For example, `Thread.sleep(500)` pauses the current thread for half a second, during which time the thread is in the `NOT RUNNABLE` state. When the specified time expires, the current thread again becomes `RUNNABLE`. CAUTION: In the JDK versions 1.0.x and 1.1, the `sleep(int` millisecond`, int` nanosecond`)` method uses the nanosecond parameter to round the millisecond parameter to the nearest millisecond. Sleeping is not yet supported in nanosecond granularity. ### Making a Thread Yield `public static void yield();` The `yield()` method is used to give a hint to the thread scheduler that now would be a good time to run other threads. If many threads are `RUNNABLE` and waiting to execute, the `yield()` method is guaranteed to switch to a different `RUNNABLE` thread only if the other thread has at least as high a priority as the current thread. #### Waiting for a Thread to End
    public final void join();
    public final void join(long millisecond);
    public final void join(long millisecond, int nanosecond);
Programs sometimes have to wait for a specific thread to terminate; this is referred to as joining the thread. To wait for a thread to terminate, invoke one of the `join()` methods on its `Thread` object. For example:
    Thread t = new OperationINeedDoneThread();
    t.start();
    .... // do some other stuff
    t.join(); // wait for the thread to complete
The two `join()` methods with time parameters are used to specify a timeout for the `join()` operation. If the thread does not terminate within the specified amount of time, `join()` returns anyway. To determine whether a timeout has happened, or whether the thread has ended, use the `Thread` method `isAlive()`. `join()` with no parameters waits forever for the thread to terminate. CAUTION: In the JDK versions 1.0.x and 1.1, the `join(int` millisecond`, int` nanosecond`)` method uses the nanosecond parameter to round the millisecond parameter to the nearest millisecond. Joining is not yet supported in nanosecond granularity. #### Understanding Daemon Threads
    public final boolean isDaemon();
    public final void setDaemon(boolean on);
Some threads are intended to be "background" threads, providing service to other threads. These threads are referred to as daemon threads. When only daemon threads remain alive, the Java virtual machine process exits. The Java virtual machine has at least one daemon thread, known as the garbage collection thread. The garbage collection thread is a low priority thread, executing only when there is nothing else for the system to do. The `setDaemon()` method sets the daemon status of this thread. The `isDaemon()` method returns `true` if this thread is a daemon thread; it returns `false` otherwise. #### Miscellaneous Thread Methods The `countStackFrames()` method returns the number of active stack frames (method activations) currently on this thread's stack. The thread must be suspended when this method is invoked. Following is this method's signature: `public int countStackFrames();``` The `getThreadGroup()` method returns the `ThreadGroup` class to which this thread belongs. A thread is always a member of a single `ThreadGroup` class. Following is this method's signature: `public final ThreadGroup getThreadGroup();``` The `isAlive()` method returns `true` if `start()` has been called on this thread and if this thread has not yet died. In other words, `isAlive()` returns `true` if this thread is `RUNNABLE` or `NOT RUNNABLE` and `false` if this thread is `NEW` or `DEAD`. Following is this method's signature: `public final boolean isAlive();``` The `currentThread()` method returns the `Thread` object for the current sequence of execution. Following is this method's signature: `public static Thread currentThread();``` The `activeCount()` method returns the number of threads in the currently executing thread's `ThreadGroup` class. Following is this method's signature: `public static int activeCount();``` The `enumerate()` method returns (through the `tarray` parameter) a list of all threads in the current thread's `ThreadGroup` class. Following is this method's signature: `public static int enumerate(Thread tarray[]);``` The `dumpStack()` method is used for debugging. It prints a method-by-method list of the stack trace for the current thread to the `System.err` output stream. Following is this method's signature: `public static void dumpStack();``` The `toString()` method returns a debugging string that describes this thread. Following is this method's prototype: `public String toString();` ### The ThreadGroup API Each Java thread belongs to exactly one `ThreadGroup` instance. The `ThreadGroup` class is used to assist with the organization and management of similar groups of threads. For example, thread groups can be used by Web browsers to group all threads belonging to a single applet. Single commands can be used to manage the entire group of threads belonging to the applet. `ThreadGroup` objects form a tree-like structure; groups can contain both threads and other groups. The top thread group is named `system`; it contains several system-level threads (such as the garbage collector thread). The `system` group also contains the `main` `ThreadGroup` object; the `main group` contains a `main` `Thread`--the thread in which `main()` is run. Figure 6.4 is a graphical representation of the `ThreadGroup` tree. #### Constructors The `ThreadGroup` class has two constructors. Both constructors require that you specify a name for the new thread group. One of the constructors takes a reference to the parent group of the new `ThreadGroup`; the constructor that does not take the parent parameter uses the group of the currently executing thread as the parent of the new group.
    public ThreadGroup(String name);
    public ThreadGroup(ThreadGroup parent, String name);
Initially, the new `ThreadGroup` object contains no threads or other thread groups. Figure 6.4. The `ThreadGroup` tree. #### Thread Helper Methods The `ThreadGroup` class contains a few methods that operate on the threads within the group. These methods are "helper" in nature; they invoke the same-named `Thread` method on all threads within the group (recursively, to thread groups within this group).
    public final void suspend();
    public final void resume();
    public final void stop();
    public final void destroy();
The helper methods include `suspend()`, `resume()`, `stop()`, and `destroy()`. Here is an example of how to stop an entire group of threads with a single method call:
    ThreadGroup group = new ThreadGroup("client threads");
    while (some_condition) {
        Thread t = new Thread(group);
        t.start();
        ...
    }
    ...
    if (kill_em_all) {   // stop all of the threads
        group.stop();
    }
The other thread group helper methods can be called in a similar manner. #### Priority `ThreadGroup` trees can assist in the management of thread priority. After calling `setMaxPriority()` on a `ThreadGroup` object, no thread within the group's tree can use `setPriority()` to set a priority higher than the specified maximum value. (Priorities of threads already in the group are not affected.)
    public final int getMaxPriority();
    public final void setMaxPriority(int pri);
The `getMaxPriority()` method returns the maximum priority value of this `ThreadGroup` tree. #### ThreadGroup Tree Navigation Each thread group can contain both threads and thread groups. The `activeCount()` and `activeCountGroup()` methods return the number of contained threads and groups, respectively. Following are the method signatures:
    public int activeCount();
    public int activeGroupCount();
The `activeCount()` method returns the number of threads that are members of this `ThreadGroup` tree (recursively). The `activeCountGroup()` method returns the number of `ThreadGroup`s that are members of this `ThreadGroup` tree (recursively). The following `enumerate()` methods can be used to retrieve the list of threads or groups in this `ThreadGroup` object:
    public int enumerate(Thread list[]);
    public int enumerate(Thread list[], boolean recurse);
    public int enumerate(ThreadGroup list[]);
    public int enumerate(ThreadGroup list[], boolean recurse);
The `recurse` parameter, if `true`, causes the retrieval of all the threads or groups within this `ThreadGroup` tree (recursively). If recurse is `false`, only the threads or groups in this immediate `ThreadGroup` object are retrieved. The `enumerate()` methods lacking the `recurse` parameter perform in the same way as the `enumerate()` methods with `recurse` set to `true`. The `parentOf()` method returns `true` if this thread group is the parent of the specified group; it returns `false` otherwise. Following is this method's syntax: `public final boolean parentOf(ThreadGroup` g); The `getParent()` method returns the parent of this thread group, or `null` if this `ThreadGroup` is the top-level `ThreadGroup`. Following is this method's syntax: `public final ThreadGroup getParent();``` The `list()` method prints debugging information about this `ThreadGroup`'s tree (threads and groups) to `System.out`. Following is this method's syntax: `public void list();` #### Miscellaneous ThreadGroup Methods The `getName()` method returns the name of this thread group. Following is this method's syntax: `public final String getName();` Some thread groups, like some threads, can be referred to as daemons. When a `ThreadGroup` object is a daemon group (`setDaemon(true)` has been called), the group is destroyed once all its threads and groups have been removed. `public final boolean isDaemon(); public final void setDaemon(boolean daemon);` The `isDaemon()` method returns `true` if this thread group is a daemon; it returns `false` otherwise. The `toString()` method returns debugging information about this thread group. Following is this method's syntax: `public String toString();` When a thread exits because it failed to catch an exception, the `uncaughtException()` method of the thread's group is invoked with the `Thread` object and the exception (`Throwable`) as parameters: `public void uncaughtException(Thread` t, Throwable e); The default behavior of `uncaughtException()` is to pass the thread and exception to the parent of this thread group. The `system` thread group, if reached, calls the `Throwable` exception's `printStackTrace()` method, dumping the stack trace of the exception to `System.err`. ### Security Features Threads and thread groups are considered critical system resources that must be protected by Java's security features. The precise implementation of the security policy depends on the environment. When running a Java application, there is no security unless you install a `SecurityManager` using `System.setSecurityManager()`. Applets, however, use the `SecurityManager` installed by the browser environment. When you run an applet under Netscape Navigator 3.0, for example, the applet is allowed to modify only the threads and thread groups created by the current applet; attempts to modify other threads or groups result in a `SecurityException`. The `Thread` class has security (as implemented by the current `SecurityManager` object) implemented for the following methods: `Thread(ThreadGroup` group`)` `Thread(ThreadGroup`group`, Runnable` target`, String` name`)` `Thread(ThreadGroup`group`, String` name`)` `stop()` `suspend(` and `resume()` `setPriority`) `setName`) `setDaemon`) The `ThreadGroup` class has security (as implemented by the current `SecurityManager` object) implemented for the following methods: `ThreadGroup(ThreadGroup` parent`, String` name`)` `setDaemon()` `setMaxPriority()` `stop()` `suspend(` and `resume()` `destroy()` ## Concurrency One of the most powerful features of the Java programming language is that it can run multiple threads of control. Performing multiple tasks at the same time seems natural from the user's perspective--for example, simultaneously downloading a file from the Internet, performing a spreadsheet recalculation, and printing a document. From a programmer's point of view, however, managing concurrency is not as natural as it seems. Concurrency requires the programmer to take special precautions to ensure that Java objects are accessed in a thread-safe manner. There is nothing obvious about threads that makes threaded programs unsafe; nevertheless, threaded programs can be subject to hazardous situations unless you take appropriate measures to make them safe. The following example demonstrates how a threaded program can be unsafe:
    public class Counter {
        private int count = 0;
        public int incr() {
            int n = count;
            count = n + 1;
            return n;
        }
    }
As Java classes go, the `Counter` class is simple, having only one attribute and one method. As its name implies, the `Counter` class is used to count things, such as the number of times a button is pressed or the number of times the user visits a particular Web site. The `incr()` method is the heart of the class, returning and incrementing the current value of the counter. However, the `incr()` method has a problem; it is a source of unpredictable behavior in a multithreaded environment. Consider a situation in which a Java program has two runnable threads, both of which are about to execute this line of code (affecting the same `Counter` object): `int cnt = counter.incr();` The programmer cannot predict or control the order in which these two threads are run. The Java thread scheduler has full authority over thread scheduling. There are no guarantees about which thread will receive CPU time, when the threads will execute, or how long each thread will be allowed to execute. Either thread may be interrupted by the scheduler at any time (remember that Java's thread scheduler is preemptive). On a multiprocessor machine, both threads may execute concurrently on separate processors. Table 6.1 describes one possible sequence of execution of the two threads. In this scenario, the first thread is allowed to run until it completes its call to `counter.incr()`; then the second thread does the same. There are no surprises in this scenario. The first thread increments the `Counter` value to `1`, and the second thread increments the value to `2`. #### Table 6.1. Counter scenario I.
Thread 1 | Thread 2 | Count
`cnt = counter.incr();` | --- | `0`
`n = count; // 0` | --- | `0`
`count = n + 1; // 1` | --- | `1`
`return n; // 0` | --- | `1`
--- | `cnt = counter.incr();` | `1`
--- | `n = count; // 1` | `1`
--- | `count = n + 1; // 2` | `2`
--- | `return n; // 1` | `2`
Table 6.2 describes a somewhat different sequence of execution. In this scenario, the first thread is interrupted by a context switch (a switch to a different thread) during execution of the `incr()` method. The first thread remains temporarily suspended, and the second thread is allowed to proceed. The second thread executes its call to the `incr()` method, incrementing the `Counter` value to `1`. When the first thread resumes, a problem becomes evident. The `Counter`'s value is not updated to the value `2`, as you would expect, but is instead set again to the value `1`. #### Table 6.2. Counter scenario II.
Thread 1 | Thread 2 | Count
`cnt = counter.incr();` | --- | `0`
`n = count; // 0` | --- | `0`
--- | `cnt = counter.incr();` | `0`
--- | `n = count; // 0` | `0`
--- | `count = n + 1; // 1` | `1`
--- | `return n; // 0` | `1`
`count = n + 1; // 1` | --- | `1`
`return n; // 0` | --- | `1`
By examining Thread 1 in Table 6.2, you can see a problematic sequence of operations. After entering the `incr()` method, the value of the `count` attribute (`0`) is stored in a local variable, `n`. The thread is then suspended for a period of time while a different thread executes. (It is important to note that the `count` attribute is modified by the second thread during this time.) When Thread 1 resumes, it stores the value `n + 1` (`1`) back in the `count` attribute. Unfortunately, this is no longer a correct value for the counter because the counter was already incremented to `1` by Thread 2. The problem outlined by Table 6.2 is called a race condition--the outcome of the program is affected by the order in which the program's threads are allocated CPU time. It is usually considered inappropriate to allow race conditions to affect a program's result. Consider a medical device that monitors a patient's blood pressure. If this device were affected by race conditions in its software, it might report an incorrect reading to the physician. The physician would base medical treatment decisions on incorrect information--a bad situation for the patient, doctor, insurance company, and software vendor! All multithreaded programs, even Java programs, can suffer from race conditions. Fortunately, Java provides the programmer with the necessary tools to manage concurrency--monitors. ### Monitors Many texts on computer science and operating systems deal with the issue of concurrent programming. Concurrency has been the subject of much research over the years, and many concurrency-control solutions have been proposed and implemented. These solutions include the following: Critical sections Semaphores Mutexes Database record locking Monitors Java implements a variant of the monitor approach to concurrency. The concept of a monitor was introduced by C. A. R. Hoare in a 1974 paper published in the Communications of the ACM. Hoare described a special-purpose object, called a monitor, which applies the principle of mutual exclusion to groups of procedures (mutual exclusion is a fancy way of saying "one thread at a time"). In Hoare's model, each group of procedures requiring mutual exclusion is placed under the control of a single monitor. At run time, the monitor allows only one thread at a time to execute a procedure controlled by the monitor. If another thread tries to invoke a procedure controlled by the monitor, that thread is suspended until the first thread completes its call. Java monitors remain true to Hoare's original concept, with a few minor variations (which are not discussed here). Monitors in Java enforce mutually exclusive access to methods; more specifically, Java monitors enforce mutually exclusive access to `synchronized` methods. (The `synchronized` keyword is an optional method modifier. If the `synchronized` keyword appears before the return type and signature of the method, the method is referred to as a "`synchronized` method.") Every Java object has an associated monitor. `synchronized` methods that are invoked on an object use that object's monitor to limit concurrent access to that object. When a `synchronized` method is invoked on an object, the object's monitor is consulted to determine whether any other thread is currently executing a `synchronized` method on the object. If no other thread is executing a `synchronized` method on that object, the current thread is allowed to enter the monitor. (Entering a monitor is also referred to as locking the monitor, or acquiring ownership of the monitor.) If a different thread has already entered the monitor, the current thread must wait until the other thread leaves the monitor. Metaphorically, a Java monitor acts as an object's gatekeeper. When a `synchronized` method is called, the gatekeeper allows the calling thread to pass and then closes the gate. While the thread is still in the `synchronized` method, subsequent `synchronized` method calls to that object from other threads are blocked. Those threads line up outside the gate, waiting for the first thread to leave. When the first thread exits the `synchronized` method, the gatekeeper opens the gate, allowing a single waiting thread to proceed with its `synchronized` method call. The process repeats. In plain English, a Java monitor enforces a one-at-a-time approach to concurrency. This is also known as serialization (not to be confused with "object serialization," which is the Java library for reading and writing objects on a stream). NOTE: Programmers already familiar with multithreaded programming in a different programming language often confuse monitors with critical sections. Java monitors are not like traditional critical sections. Declaring a method `synchronized` does not imply that only one thread at a time can execute that method, as is the case with a critical section. Monitors imply that only one thread can invoke that method (or any `synchronized` method) on a particular object at any given time. Java monitors are associated with objects, not with blocks of code. Two threads can concurrently execute the same synchronized method, provided that the method is invoked on different objects (that is, `a.method()` and `b.method()`, where `a != b`). To demonstrate how monitors operate, let's rewrite the `Counter` example from the preceding section to take advantage of monitors, using the `synchronized` keyword:
    public class Counter2 {
        private int count = 0;
        public synchronized int incr() {
            int n = count;
            count = n + 1;
            return n;
        }
    }
Note that the `incr()` method has not been modified except for the addition of the `synchronized` keyword. What would happen if this new `Counter2` class were used in the scenario presented in Table 6.2 (the race condition)? The outcome of the same sequence of context switches is listed in Table 6.3. #### Table 6.3. Counter scenario II, revised.
Thread 1 | Thread 2 | Count
`cnt = counter.incr();` | --- | `0`
`(acquires the monitor)` | --- | `0`
`n = count; // 0` | --- | `0`
--- | `cnt = counter.incr();` | `0`
--- | (can't acquire monitor) | `0`
`count = n + 1; // 1` | (blocked) | `1`
`return n; // 0` | (blocked) | `1`
`(releases the monitor)` | (blocked) | `1`
--- | (acquires the monitor) | `1`
--- | `n = count; // 1` | `1`
--- | `count = n + 1; // 2` | `2`
--- | `return n; // 1` | `2`
--- | (releases the monitor) | `2`
In Table 6.3, the sequence of operations begins the same as the scenario in Table 6.2. Thread 1 starts executing the `incr()` method of the `Counter2` object but is interrupted by a context switch. In this example, however, when Thread 2 attempts to execute the `incr()` method on the same `Counter2` object, the thread can't acquire the monitor and is blocked; the monitor is already owned by Thread 1. Thread 2 is suspended until the monitor becomes available. When Thread 1 releases the monitor, Thread 2 can then acquire the monitor and continue running. The `synchronized` keyword is Java's solution to the concurrency control problem. As you saw in the `Counter` example, the potential race condition was eliminated by adding the `synchronized` modifier to the `incr()` method. All accesses to the `incr()` method of a counter were serialized by the addition of the `synchronized` keyword. Generally speaking, any method that modifies an object's attributes should be synchronized with the `synchronized` keyword. NOTE: You may be wondering when you will see an actual monitor object. Anecdotal information has been presented about monitors, but you probably want to see some official documentation about what a monitor is and how you access it. Unfortunately, that is not possible. Java monitors have no official standing in the language specification, and their implementation is not directly visible to the programmer. Monitors are not Java objects--they have no attributes or methods. Monitors are a concept beneath Java's implementation of multithreading and concurrency. It is possible to access Java monitors at the native code level in the 1.x release of the Java virtual machine from Sun--the 1.1 Java Native Interface specification defines two methods that operate on monitors: `MonitorEnter()` and `MonitorExit()`. ### Non-synchronized Methods Java monitors are used only in conjunction with `synchronized` methods. Methods that are not declared `synchronized` do not attempt to acquire ownership of an object's monitor before executing--they ignore monitors entirely. At any given moment, at most one thread can execute a `synchronized` method on an object, but an arbitrary number of threads can execute non-`synchronized` methods. This can lead to some surprising situations if you are not careful in deciding which methods should be synchronized. Consider the `Account` class in Listing 6.4. #### Listing 6.4. The Account class.
    class Account {
      private int balance;
      public Account(int balance) {
        this.balance = balance;
      }
      public synchronized void transfer(int amount, Account destination) {
        synchronized (destination) {
          this.withdraw(amount);
          Thread.yield();     // force a context switch
          destination.deposit(amount);
        }
      }
      public synchronized void withdraw(int amount) {
        if (amount > balance) {
          throw new RuntimeException("No overdraft protection!");
        }
        balance -= amount;
      }
      public synchronized void deposit(int amount) {
        balance += amount;
      }
      public int getBalance() {
        return balance;
      }
    }
The attribute-modifying methods of the `Account` class are declared `synchronized`, but the `getBalance()` method is not synchronized. It appears that this class has no problem with race conditions--but it does! To understand the race condition to which the `Account` class is subject, consider how a bank deals with accounts. To a bank, the correctness of its accounts is of the utmost importance--a bank that makes accounting errors or reports incorrect information would not have happy customers. To avoid reporting incorrect information, a bank would likely disable "inquiries" on an account while a transaction involving the account is in progress. This prevents the customer from viewing the result of a partially complete transaction. In Listing 6.4, the `Account` class's `getBalance()` method is not `synchronized`, and this can lead to problems. Consider two `Account` objects and two different threads performing actions on these accounts. One thread is performing a balance transfer from one account to the other. The second thread is performing a balance inquiry. This code demonstrates the suggested activity:
    public class XferTest implements Runnable {
      public static void main(String[] args) {
        XferTest xfer = new XferTest();
        xfer.a = new Account(100);
        xfer.b = new Account(100);
        xfer.amount = 50;
        Thread t = new Thread(xfer);
        t.start();
        Thread.yield();    // force a context switch
        System.out.println("Inquiry: Account a has : $" + xfer.a.getBalance());
        System.out.println("Inquiry: Account b has : $" + xfer.b.getBalance());
      }
      public Account a = null;
      public Account b = null;
      public int amount = 0;
      public void run() {
        System.out.println("Before xfer: a has : $" + a.getBalance());
        System.out.println("Before xfer: b has : $" + b.getBalance());
        a.transfer(amount, b);
        System.out.println("After xfer: a has : $" + a.getBalance());
        System.out.println("After xfer: b has : $" + b.getBalance());
      }
    }
In this example, two `Account`s are created, each with a $100 balance. A transfer is then initiated to move $50 from one account to the other. The transfer is not an operation that should affect the total balance of the two accounts; that is, the sum of the balance of the two accounts should remain constant at $200. If the balance inquiry is performed at just the right time, however, it is possible that the total amount of funds in these accounts could be incorrectly reported. If this program is run using the JDK version 1.0 for Solaris, the following output is printed:
    Before xfer: a has : $100
    Before xfer: b has : $100
    Inquiry: Account a has : $50
    Inquiry: Account b has : $100
    After xfer: a has : $50
    After xfer: b has : $150
The inquiry reports that the first account contains $50 and the second account contains $100. That's not $200! What happened to the other $50? Nothing has "happened" to the money--except that it is in the process of being transferred to the second account when the balance inquiry scans the accounts. Because the `getBalance()` method is not synchronized, a customer would have no problem executing an inquiry on accounts involved in the balance transfer. The lack of synchronization can leave some customer wondering why the accounts are $50 short. If the `getBalance()` method is declared `synchronized`, the application has a different result. The modified code follows:
    public synchronized int getBalance() {
        return balance;
      }
The balance inquiry is blocked until the balance transfer is complete. Here is the modified program's output:
    Before xfer: a has : $100
    Before xfer: b has : $100
    Inquiry: Account a has : $50
    Inquiry: Account b has : $150
    After xfer: a has : $50
    After xfer: b has : $150
## Advanced Monitor Concepts Monitors sound pretty simple. Add the `synchronized` modifier to your methods, and that's all there is to it. Well, not quite. Monitors themselves may be simple, but taken together with the rest of the programming environment, there are a few issues you should understand before you use `synchronized` methods. The following sections present a few tips and techniques you should master to become expert in concurrent Java programming. ### static synchronized Methods Methods that are declared `synchronized` attempt to acquire ownership of the target object's monitor. But what about `static` methods (methods that do not have an associated object)? The language specification is fairly clear, if brief, about `static synchronized` methods. When a `static synchronized` method is called, the monitor acquired is said to be a per-class monitor--that is, there is one monitor for each class that regulates access to all `static` methods of that class. Only one `static synchronized` method in a class can be active at a given moment. ### The synchronized Statement It is not possible to use `synchronized` methods on some types of objects. For example, it is not possible to add any methods to Java array objects (much less `synchronized` methods). To get around this restriction, Java has a second way of interacting with an object's monitor. The `synchronized` statement is defined to have the following syntax: `synchronized ( Expression ) Statement` Executing a `synchronized` statement has the same effect as calling a `synchronized` method--ownership of an object's monitor is acquired before a block of code can be executed. With the `synchronized` statement, the object whose monitor is up for grabs is the object resulting from Expression (which must be an object type, not an elemental type like `int`, `double`, and so on). One of the most important uses of the `synchronized` statement involves controlling access to array objects. The following example demonstrates how to use the `synchronized` statement to provide thread-safe access to an array:
    void safe_lshift(byte[] array, int count) {
        synchronized(array) {
            System.arraycopy(array, count, array, 0, array.size - count);
        }
    }
Before modifying the array in this example, the virtual machine assigns ownership of `array`'s monitor to the currently executing thread. Other threads trying to acquire `array`'s monitor are forced to wait until the array-copy operation is complete. Of course, accesses to the array that are not guarded by a `synchronized` statement are not blocked; so be careful! The `synchronized` statement is also useful when modifying an object's `public` variables directly. Here's an example:
    void call_method(SomeClass obj) {
        synchronized(obj) {
            obj.variable = 5;
        }

    }
PUBLIC OR NOT? There is debate within the Java community about the potential danger of declaring attributes to be `public`. When concurrency is considered, it becomes apparent that `public` attributes can lead to thread-unsafe code. Here's why: `public` attributes can be accessed by any thread without the benefit of protection by a `synchronized` method. When you declare an attribute `public`, you relinquish control over updates to that attribute; any programmer using your code has a license to access (and update) `public` attributes directly. In general, it is not a good idea to declare non-`final` attributes to be `public`. Not only can doing so introduce thread-safety problems, it can make your code difficult to modify and support in later revisions. Note, however, that Java programmers frequently define immutable symbolic constants as `public final` class attributes (such as `Event.ACTION_EVENT`). Attributes declared this way do not have thread-safety issues. (Race conditions involve only objects whose values can be modified.) ### When Not to Be synchronized By now, you should be able to write thread-safe code using the `synchronized` keyword. When should you really use the `synchronized` keyword? Are there situations in which you should not use `synchronized`? Are there drawbacks to using `synchronized`? The most common reason developers don't use `synchronized` is that they write single-threaded, single-purpose code. For example, CPU-bound tasks do not benefit much from multithreading. A compiler does not perform much better if it is threaded. The Java compiler from Sun does not contain many `synchronized` methods. For the most part, it assumes that it is executing in its own thread of control, without having to share its resources with other threads. Another common reason for avoiding `synchronized` methods is that they do not perform as well as non-`synchronized` methods. In simple tests in the JDK version 1.0.1 from Sun, `synchronized` methods have been shown to be three to four times slower than their non-`synchronized` counterparts. Although this doesn't mean your entire application will be three or four times slower, it is a performance issue nonetheless. Some programs demand that every ounce of performance be squeezed out of the runtime system. In this situation, it may be appropriate to avoid the performance overhead associated with `synchronized` methods. ### Java 1.1 Inner Classes With the release of Java 1.1, Java now supports inner classes (refer to Chapter 5, "Classes, Packages, and Interfaces," for an introduction to inner classes). Inner classes are classes declared within another class. An instance of an inner class has a special relationship to an instance of the outer class--referred to as the enclosing instance. Inner-class instances are permitted to access all the fields of the enclosing instance, including `private` fields. Additionally, an inner-class instance can modify the variables of its enclosing instance. Inner classes introduce potential problems for programs that use threads. Consider the following example of an inner class and an enclosing class:
    public class Enclosing {
      private int privateVar = 1;
      public synchronized void update() {
        privateVar = privateVar + 1;
      }
      public class Inner {
        public synchronized void update() {
          privateVar = privateVar + 1;
        }
      }
    }
The `Enclosing` class has three fields: a `private` variable, a `synchronized` method, and the `Inner` class. This example demonstrates that the `private` variables of an enclosing instance can be updated from methods of the enclosing instance and the inner instance--both `Enclosing` and `Inner` have an `update()` method that modifies `privateVar`. Calling a `synchronized` method from the enclosing instance is a safe way to update the enclosing instance:
    Enclosing enclosingInstance = getEnclosingInstance();
    enclosingInstance.update(); // SAFE
However, it is not particularly safe to call a `synchronized` method from an inner instance to update the enclosing instance:
    Enclosing enclosingInstance = getEnclosingInstance();
    Enclosing.Inner innerInstance = enclosingInstance.new Inner();
    innerInstance.update(); // UNSAFE
This second code example is unsafe because the use of inner classes involves more than one object--and thus, more than one monitor. When the code `innerInstance.update()` is called, the only monitor acquired is that of the `innerInstance`. The monitor of the `enclosingInstance` is never acquired, even though its `privateVar` is updated. To make the code thread safe, the `Inner` class's `update()` method should acquire the monitor of its enclosing instance, like this:
    class Inner {
      public synchronized void update() {
        synchronized (Enclosing.this) {      // must also lock the enclosing instance
          privateVar = privateVar + 1;
        }
      }
    }
In general, inner classes that access variables from an enclosing instance should use the `synchronized` statement to lock the enclosing instance while its variables are being accessed. The generalized form for this type of lock follows:
    synchronized (name-of-enclosing-class . this) {
    // your code here
    }
### Deadlocks Sometimes referred to as a deadly embrace, a deadlock is one of the worst situations that can happen in a multithreaded environment. Java programs are not immune to deadlocks, and programmers must take care to avoid them. A deadlock is a situation that causes two or more threads to hang, that is, to be unable to proceed. In the simplest case, two threads are each trying to acquire a monitor that is already owned by the other thread. Each thread goes to sleep, waiting for the desired monitor to become available--but the monitors never become available. (The first thread waits for the monitor owned by the second thread, and the second thread waits for the monitor owned by the first thread. Because each thread is waiting for the other, it never releases its monitor to the other thread.) The sample application in Listing 6.5 should give you an understanding of how a deadlock happens. #### Listing 6.5. A deadlock.
    public class Deadlock implements Runnable {
      public static void main(String[] args) {
            Deadlock d1 = new Deadlock();
            Deadlock d2 = new Deadlock();
            Thread t1 = new Thread(d1);
            Thread t2 = new Thread(d2);
            d1.grabIt = d2;
            d2.grabIt = d1;
            t1.start();
            t2.start();
            try { t1.join(); t2.join(); } catch(InterruptedException e) { }
            System.exit(0);
      }
      Deadlock grabIt;
      public synchronized void run() {
            try { Thread.sleep(2000); } catch(InterruptedException e) { }
            grabIt.sync_method();
      }
      public synchronized void sync_method() {
            try { Thread.sleep(2000); } catch(InterruptedException e) { }
            System.out.println("in sync_method");
      }
    }
> In this class, `main()` launches two threads, each of which invokes the `synchronized run()` method on a `Deadlock` object. When the first thread wakes up, it attempts to call the `sync_method()` of the other `Deadlock` object. Obviously, the second `Deadlock`'s monitor is owned by the second thread, so the first thread begins waiting for the monitor. When the second thread wakes up, it tries to call the `sync_method()` of the first `Deadlock` object. Because that `Deadlock`'s monitor is already owned by the first thread, the second thread begins waiting. Because the threads are waiting for each other, neither will ever wake up. NOTE: If you run the deadlock application shown in Listing 6.5, you will notice that it never exits. That is understandable; after all, that is what a deadlock is. How can you tell what is really going on inside the virtual machine? There is a trick you can use with the Solaris/UNIX JDK to display the status of all threads and monitors: Press Ctrl+\ in the terminal window in which the Java application is running. This action sends the virtual machine a signal to dump the state of the VM. Here is a partial listing of the monitor table dumped several seconds after launching the deadlock application:
>     Deadlock@EE300840/EE334C20 (key=0xee300840):     monitor owner: "Thread-5"
>         Waiting to enter:
>             "Thread-4"
>     Deadlock@EE300838/EE334C18 (key=0xee300838):     monitor owner: "Thread-4"
>         Waiting to enter:
>           "Thread-5"
Numerous algorithms are available for preventing and detecting deadlock situations, but those algorithms are beyond the scope of this chapter (many database and operating system texts cover deadlock-detection algorithms in detail). Unfortunately, the Java virtual machine itself does not perform any deadlock detection or notification. There is nothing that prevents the virtual machine from doing so, however, so this behavior may be added to future versions of the virtual machine. ### Using volatile It is worth mentioning that the `volatile` keyword is supported as a variable modifier in Java. The language specification states that the `volatile` qualifier instructs the compiler to generate loads and stores on each access to an attribute, rather than caching the value in a register. The intent of the `volatile` keyword is to provide thread-safe access to an attribute, but `volatile` falls short of this goal. In the 1.x JDK virtual machine, the `volatile` keyword is ignored. It is unclear whether `volatile` has been abandoned in favor of monitors and `synchronized` methods or whether the keyword was included solely for a C and C++ look and feel. Regardless, `volatile` is useless--use `synchronized` methods rather than the `volatile` keyword. ## Synchronization After learning how `synchronized` methods are used to make Java programs thread safe, you may wonder what the big deal is about monitors. They are just object locks, right? Not true! Monitors are more than locks; monitors are also used to coordinate multiple threads by using the `wait()` and `notify()` methods available in every Java object. ### The Need for Thread Coordination In a Java program, threads are often interdependent--one thread can depend on another thread to complete an operation or to service a request. For example, a spreadsheet program can run an extensive recalculation as a separate thread. If a user-interface (UI) thread attempts to update the spreadsheet's display, the UI thread should coordinate with the recalculation thread, starting the screen update only when the recalculation thread has successfully completed. There are many other situations in which it is useful to coordinate two or more threads. The following list identifies only some of the possibilities: Shared buffers are often used to communicate data between threads. In this scenario, one thread writes to a shared buffer (the writer) and one thread reads from the buffer (the reader). When the reader thread attempts to read from the buffer, it should coordinate with the writer thread, retrieving data from the shared buffer only after the writer thread has put it there. If the buffer is empty, the reader thread should wait for the data. The writer thread notifies the reader thread when it has completed filling the buffer so that the reader can continue. Many threads may have to perform an identical action, such as loading an image file across the network. These threads can reduce the overall system load if only one thread performs the work while the other threads wait for the work to be completed. (The waiting threads must wait without consuming CPU time by temporarily transitioning into the `NOT RUNNABLE` thread state; this is possible, and is discussed later in this chapter.) This is precisely the model used in the `java.awt.MediaTracker` class. It is no accident that the previous examples repeatedly use the words wait and notify. These words express the two concepts central to thread coordination: A thread waits for some condition or event to occur, and you notify a waiting thread that a condition or event has occurred. The words wait and notify are also used in Java as the names of the methods you call to coordinate threads: `wait()` and `notify()`, in class `Object`. As noted in "Monitors," earlier in this chapter, every Java object has an associated monitor. That fact turns out to be useful at this point because monitors are also used to implement Java's thread-coordination primitives. Although monitors are not directly visible to the programmer, an API is provided in class `Object` that enables you to interact with an object's monitor. This API consists of two methods: `wait()` and `notify()`. ### Conditions, wait(), and notify() Threads are usually coordinated using a concept known as a condition, or a condition variable. A condition is a logical statement that must hold true in order for a thread to proceed; if the condition does not hold true, the thread must wait for the condition to become true before continuing. In Java, this pattern is usually expressed as follows:
    while ( ! the_condition_I_am_waiting_for ) {
        wait();
    }
First, check to see whether the desired condition is already true. If it is true, there is no need to wait. If the condition is not yet true, call the `wait()` method. When `wait()` ends, recheck the condition to make sure that it is now true. Invoking `wait()` on an object pauses the current thread and adds the thread to the condition variable wait queue of the object's monitor. This queue contains a list of all the threads that are currently blocked inside `wait()` on that object. The thread is not removed from the wait queue until `notify()` is invoked on that object from a different thread. A call to `notify()` wakes a single waiting thread, notifying the thread that a condition of the object has changed. There are two additional varieties of the `wait()` method. The first version takes a single parameter--a timeout value in milliseconds. The second version has two parameters--a more precise timeout value, specified in milliseconds and nanoseconds. These methods are used when you do not want to wait indefinitely for an event. If you want to abandon the wait after a fixed period of time (referred to as timing out), you should use either of the following methods: `wait(long milliseconds);` `wait(long milliseconds, int nanoseconds);` Unfortunately, these methods do not provide a way to determine how the `wait()` was ended--whether a `notify()` occurred or whether the method timed out. This is not a big problem, however, because you can recheck the wait condition and the system time to determine which event has occurred. CAUTION: In the JDK versions 1.0.x and 1.1, the `wait(int` millisecond`, int` nanosecond`)` method uses the nanosecond parameter to round the millisecond parameter to the nearest millisecond. Waiting is not yet supported in nanosecond granularity. The `wait()` and `notify()` methods must be invoked from within a `synchronized` method or from within a `synchronized` statement. This requirement is discussed in further detail in "Monitor Ownership," later in this chapter. ### A Thread Coordination Example A classic example of thread coordination used in many computer science texts is the bounded buffer problem. This problem involves using a fixed-size memory buffer to communicate between two processes or threads. To solve this problem, you must coordinate the reader and writer threads so that the following are true: When the writer thread attempts to write to a full buffer, the writer is suspended until some items are removed from the buffer. When the reader thread removes items from the full buffer, the writer thread is notified of the buffer's changed condition and may continue writing. When the reader thread attempts to read from an empty buffer, the reader is suspended until some items are added to the buffer. When the writer adds items to the empty buffer, the reader thread is notified of the buffer's changed condition and may continue reading. The following class listings demonstrate a Java implementation of the bounded buffer problem. There are three main classes in this example: the `Producer`, the `Consumer`, and the `Buffer`. Let's start with the `Producer`:
    public class Producer implements Runnable {
      private Buffer buffer;
      public Producer(Buffer b) {
            buffer = b;
      }
      public void run() {
          for (int i=0; i<250; i++) {
              buffer.put((char)('A' + (i%26)));   // write to the buffer
          }
      }
    }
The `Producer` class implements the `Runnable` interface (which should give you a hint that it will be used in a `Thread`). When the `Producer`'s `run()` method is invoked, 250 characters are written in rapid succession to a buffer. The `Consumer` class is as simple as the `Producer`:
    public class Consumer implements Runnable {
      private Buffer buffer;
      public Consumer(Buffer b) {
            buffer = b;
      }
      public void run() {
            for (int i=0; i<250; i++) {
              System.out.println(buffer.get());    // read from the buffer
            }
      }
    }
The `Consumer` is also a `Runnable` interface. Its `run()` method greedily reads 250 characters from a buffer. The `Buffer` class has been mentioned already, including two of its methods: `put(char)` and `get()`. Listing 6.6 shows the `Buffer` class in its entirety. #### Listing 6.6. The Buffer class.
    public class Buffer {
      private char[] buf;   // buffer storage
      private int last;     // last occupied position
      public Buffer(int sz) {
            buf = new char[sz];
            last = 0;
      }
      public boolean isFull()  { return (last == buf.length); }
      public boolean isEmpty() { return (last == 0);          }
      public synchronized void put(char c) {
            while(isFull()) {                    // wait for room to put stuff
              try { wait(); } catch(InterruptedException e) { }
            }
            buf[last++] = c;
            notify();
      }
      public synchronized char get() {
            while(isEmpty()) {                   // wait for stuff to read
              try { wait(); } catch(InterruptedException e) { }
            }
            char c =  buf[0];
            System.arraycopy(buf, 1, buf, 0, --last);
            notify();
            return c;
      }
    }
NOTE: When you first begin using `wait()` and `notify()`, you may notice a contradiction. The `wait()` and `notify()` methods must be called from `synchronized` methods, so if `wait()` is called inside a `synchronized` method, how can a different thread enter a `synchronized` method in order to call `notify()`? Doesn't the waiting thread own the object's monitor, preventing other threads from entering the `synchronized` method? The answer to this paradox is that `wait()` temporarily releases ownership of the object's monitor; before `wait()` can return, however, it must reacquire ownership of the monitor. By releasing the monitor, the `wait()` method allows other threads to acquire the monitor (which gives them the ability to call `notify()`). The `Buffer` class is just that--a storage buffer. You can use `put()` to put items into the buffer (in this case, characters), and you can use `get()` to get items out of the buffer. Note the use of `wait()` and `notify()` in these methods. In the `put()` method, a `wait()` is performed while the buffer is full; no more items can be added to the buffer while it is full. At the end of the `get()` method, the call to `notify()` ensures that any thread waiting in the `put()` method will be activated and allowed to continue adding an item to the buffer. Similarly, a `wait()` is performed in the `get()` method if the buffer is empty; no items can be removed from an empty buffer. The `put()` method calls `notify()` to ensure that any thread waiting in `get()` will be wakened. NOTE: Java provides two classes similar to the `Buffer` class presented in this example. These classes, `java.io.PipedOutputStream` and `java.io.PipedInputStream`, are useful in communicating streams of data between threads. If you unpack the `src.zip` file shipped with the JDK, you can examine these classes to see how they handle interthread coordi-nation. ### Advanced Thread Coordination The `wait()` and `notify()` methods simplify the task of coordinating multiple threads in a concurrent Java program. However, to make full use of these methods, you should understand a few additional details. The following sections present more material about thread coordination in Java. #### Monitor Ownership The `wait()` and `notify()` methods have one major restriction you must observe: You can call these methods only when the current thread owns the monitor of the object. Most frequently, `wait()` and `notify()` are invoked from within a `synchronized` method, as in the following example:
    public synchronized void method() {
        ...
        while (!condition) {
          wait();
        }
        ...
    }
In this case, the `synchronized` modifier guarantees that the thread invoking the `wait()` call already owns the monitor when it calls `wait()`. If you attempt to call `wait()` or `notify()` without first acquiring ownership of the object's monitor (for example, from a non-`synchronized` method), the virtual machine throws an `IllegalMonitorStateException`. The following example demonstrates what happens when you call `wait()` without first acquiring ownership of the monitor:
    public class NonOwnerTest {
      public static void main(String[] args) {
            NonOwnerTest not = new NonOwnerTest();
            not.method();
      }
      public void method() {
            try { wait(); } catch(InterruptedException e) { }   // a bad thing to do!
      }
    }
If you run this Java application, the following text is printed to the terminal:
    java.lang.IllegalMonitorStateException: current thread not owner
            at java.lang.Object.wait(Object.java)
            at NonOwnerTest.method(NonOwnerTest.java:10)
            at NonOwnerTest.main(NonOwnerTest.java:5)
  When you invoke the `wait()` method on an object, you must own the object's monitor if you are to avoid this exception. MONITORS AND THE synchronized STATEMENT: All Java objects can participate in thread synchronization by using the `wait()` and `notify()` methods. However, the "monitor ownership" requirement introduces a quirk for some object types, such as arrays. (Strangely enough, Java array types inherit from the `java.lang.Object` class, where the `wait()` and `notify()` methods are defined.) The `wait()` and `notify()` methods can be called on Java array objects, but monitor ownership must be established using the `synchronized` statement rather than a synchronized method. The following code demonstrates monitor usage as applied to a Java array:
      // wait for an event on this array
      Object[] array = getArray();
      synchronized (array) {
      array.wait();
      }
      ...
      // notify waiting threads
      Object[] array = getArray();
      synchronized (array) {
      array.notify();
      }
#### Multiple Waiters It is possible for multiple threads to be waiting on the same object. This can happen when multiple threads wait for the same event. For example, recall the `Buffer` class described earlier; the b`uffer` was operated on by a single `Producer` and a single `Consumer`. What would happen if there were multiple `Producer`s? If the buffer filled, different `Producer`s might attempt to use `put()` to place items into the buffer; they would all block inside the `put()` method, waiting for a `Consumer` to come along and free up space in the buffer. When you call `notify()`, there may be zero, one, or more threads blocked in a `wait()` on the monitor. If there are no threads waiting, the call to `notify()` is a no-op--it does not affect any other threads. If there is a single thread in `wait()`, that thread is notified and begins waiting for the monitor to be released by the thread that called `notify()`. If two or more threads are in a `wait()`, the virtual machine picks a single waiting thread and notifies that thread. (The method used to "pick" a waiting thread varies from platform to platform--your programs should not rely on the VM to select a specific thread from the pool of waiting threads.) #### Using notifyAll() In some situations, you may want to notify every thread currently waiting on an object. The `Object` API provides a method to do this: `notifyAll()`. The `notify()` method wakes only a single waiting thread, but the `notifyAll()` method wakes every thread currently waiting on the object. When would you want to use `notifyAll()`? Consider the `java.awt.MediaTracker` class. This class is used to track the status of images being loaded over the network. Multiple threads may wait on the same `MediaTracker` object, waiting for all the images to be loaded. When the `MediaTracker` detects that all images have been loaded, `notifyAll()` is called to inform every waiting thread that the images have been loaded. `notifyAll()` is used because the `MediaTracker` does not know how many threads are waiting; if `notify()` were used, some of the waiting threads may not receive notification that the transfer was completed. These threads would continue waiting, probably hanging the entire applet. Listing 6.6, earlier in this chapter, can also benefit from the use of `notifyAll()`. In that code, the `Buffer` class used the `notify()` method to send a notification to a single thread waiting on an empty or a full buffer. However, there was no guarantee that only a single thread was waiting; multiple threads may have been waiting for the same condition. Listing 6.7 shows a modified version of the `Buffer` class (named `Buffer2`) that uses `notifyAll()`. #### Listing 6.7. The Buffer2 class, using notifyAll().
    public class Buffer2 {
      private char[] buf;               // storage
      private int last = 0;             // last occupied position
      private int writers_waiting = 0;  // # of threads waiting in put()
      private int readers_waiting = 0;  // # of threads waiting in get()
      public Buffer2(int sz) {
            buf = new char[sz];
    }
      public boolean isFull()  { return (last == buf.length); }
      public boolean isEmpty() { return (last == 0);          }
      public synchronized void put(char c) {
            while(isFull()) {
              try     { writers_waiting++;  wait(); }
              catch   (InterruptedException e) { }
              finally { writers_waiting--; }
            }
            buf[last++] = c;
            if (readers_waiting > 0) {
              notifyAll();
            }
      }
      public synchronized char get() {
            while(isEmpty()) {
              try     { readers_waiting++;  wait(); }
              catch   (InterruptedException e) { }
              finally { readers_waiting--; }
            }
            char c =  buf[0];
            System.arraycopy(buf, 1, buf, 0, --last);
            if (writers_waiting > 0) {
              notifyAll();
            }
            return c;
      }
    }
The `get()` and `put()` methods have been made more intelligent. They now check to see whether any notification is necessary and then use `notifyAll()` to broadcast an event to all waiting threads. ## Summary This chapter was a whirlwind tour of multithreaded programming in Java. Among other things, the chapter covered the following: Creating your own thread classes by subclassing `Thread` or implementing `Runnable` Using the `ThreadGroup` class to manage groups of threads Understanding thread states and thread scheduling Making your classes thread-safe by using the `synchronized` keyword to protect objects from concurrent modification Understanding how monitors affect concurrent programming in Java Coordinating the actions of multiple threads by calling the `wait()` and `notify()` methods Java threads are not difficult to use. After reading this chapter, you should begin to see how threads can be used to improve your everyday Java programming.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.