Thread Definition

A thread is a single flow of control within a program. It is sometimes called the execution context because each thread must have its own resources, like the program counter and the execution stack, as the context for execution. However, all threads in a program still share many resources, such as memory space and opened files. Therefore, a thread may also be called a lightweight process.

NOTE: It is easier to create and destroy a thread than a process.

Parallel and Concurrent Threads

When two threads run in parallel, they are both being executed at the same time on different CPUs. Two concurrent threads are both in progress, or trying to get some CPU time for execution at the same time, but are not necessarily being executed simultaneously on different CPUs.

Improved CPU Utilization
A program may spend a big portion of its execution time waiting. For example, it may wait for a resource to become accessible in an I/O operation, or it may wait for a time-out to occur to start drawing the next scene of an animation sequence. To improve CPU utilization, tasks with potentially long waits can run as separate threads. Once a task starts waiting for something to happen, the Java run time can choose another runnable task for execution

Single-Threaded Program Example
In the program shown here, a run() method in the NoThreadPseudoIO class is created to simulate a 10-second I/O operation. The main program will first perform the simulated I/O operation

Single-Threaded Program Methods
The method showElapsedTime() is defined to print the time elapsed in seconds since the program started, together with a user-supplied message. The currentTimeMillis() method of the System class in the java.lang package will return a long integer for the time difference, measured in milliseconds, between the current time and 00:00:00 GMT on January 1, 1970.

NOTE: The times shown will vary depending on machine types and environments.

Single-Threaded Program Methods
The method showElapsedTime() is defined to print the time elapsed in seconds since the program started, together with a user-supplied message. The currentTimeMillis() method of the System class in the java.lang package will return a long integer for the time difference, measured in milliseconds, between the current time and 00:00:00 GMT on January 1, 1970.

NOTE: The times shown will vary depending on machine types and environments.

Multithreaded Program Example
The multithreaded program declares the class for the simulated I/O operation as a subclass of the Thread class. After the thread is created, the multithreaded program uses the start() method of the Thread class to start the I/O operation. The start() method in turn calls the run() method of the subclass.

Creating and Running Threads
There are two methods for making a task run concurrently with other tasks: create a new class as a subclass of the Thread class or declare a class by implementing the Runnable interface

Use Subclass
When you create a subclass of the Thread class, this subclass should define its own run() method to override the run() method of the Thread class. This run() method is where the task is performed.

Execute run() Method
The run() method is the first user-defined method the Java runtime calls when a thread is started. An instance of the subclass is then created by a new statement, followed by a call to the thread's start() method to have the run() method executed.

Implement Runnable Interface
The Runnable interface requires only one method to be implemented-the run() method. You first create an instance of this class with a new statement, followed by the creation of a Thread instance with another new statement. Finally, call this thread instance's start() method to start performing the task defined in the run() method

Indicate run() Method
A class instance with the run() method defined within it must be passed in as an argument in creating the Thread instance, so that when the start() method of this Thread instance is called, Java run time knows which run() method to execute.

Re-Implement Multithreaded Program
A multithreaded program can be re-implemented using the Runnable interface by first changing the class definition to implement the Runnable interface, instead of subclassing the Thread class. An instance of the class is created and passed to a newly created Thread instance, followed by a call to the start() method to start the execution of the run() method.

Controlling Thread Executions
Many methods defined in the java.lang.Thread class control the running of a thread. Java 2 deprecated several of them to prevent data inconsistencies or deadlocks. If you are just starting with Java 2, avoid the deprecated methods and use the equivalent behavior. However, if you are transitioning from Java 1.0 or 1.1, you will need to modify your code to avoid the deprecated methods if you used them. Some of the most commonly used methods are examined in this section.

void start
The void start() method is used to start the execution of the thread body defined in the run() method. Program control will be immediately returned to the caller, and a new thread will be scheduled to execute the run() method concurrently with the caller's thread.

void stop
The void stop() method is deprecated and used to stop the execution of the thread no matter what the thread is doing. The thread is then considered dead, the internal states of the thread are cleared, and the resources allocated are reclaimed. Using this method has the potential to leave data in an inconsistent state and should be avoided.

void suspend
The void suspend() method is deprecated and used to temporarily stop the execution of the thread. All the states and resources of the thread are retained. The thread can later be restarted by another thread calling the resume() method. Using this method has a strong potential for deadlocks and should be avoided. You should use the Object.wait() method instead.

void resume
The void resume() method is deprecated and used to resume the execution of a suspended thread. The suspended thread will be scheduled to run. If it has a higher priority than the running thread, the running thread will be preempted; otherwise, the just-resumed thread will wait in the queue for its turn to run. Using this method has a strong potential for deadlocks and should be avoided. You should use the Object.notify() method instead.

static void sleep
The static void sleep() method is a class method that causes the Java run time to put the caller thread to sleep for a minimum of the specified time period. The exception, InterruptedException, may be thrown while a thread is sleeping or any time if you interrupt() it. Either a try-catch statement needs to be defined to handle this exception or the enclosing method needs to have this exception in the throws clause.

void join
The void join() method is used for the caller's thread to wait for this thread to die-for example, by coming to the end of the run() method.

static void yield
The static void yield() method is a class method that temporarily stops the caller's thread and puts it at the end of the queue to wait for another turn to be executed. It is used to make sure other threads of the same priority have the chance to run.

Caller's Thread
All the class methods defined in the Thread class, such as sleep() and yield(), will act on the caller's thread. That is, it is the caller's thread that will sleep for a while or yield to others.

NOTE: The reason is that a class method can never access an instance's data or method members unless the instance is passed in as an argument, created inside the method, or stored in a class variable visible to the method.

Thread Execution Example
In the example shown here, the main thread creates two threads, and then waits for the first thread to finish by calling the first thread's join() method. The first thread calls the sleep() method to be asleep for 10 seconds.

Second Thread
The second thread calls its own wait() method to suspend itself. After the first thread comes to an end, the main thread will resume its execution, wake up the second thread by calling the second thread's notify() method, and wait until the second thread also comes to an end by calling the second thread's join() method.

Thread Life Cycle
Every thread, after creation and before destruction, will always be in one of four states: newly created, runnable, blocked, or dead

New Threads
A thread enters the newly created state immediately after creation; that is, it enters the state right after the thread-creating new statement is executed. In this state, the local data members are allocated and initialized, but execution of the run() method will not begin until its start() method is called. After the start() method is called, the thread will be put into the runnable state.

Runnable Threads
When a thread is in the runnable state, the execution context exists and the thread can be scheduled to run at any time; that is, the thread is not waiting for any event to happen.

Running and Queued States
The runnable state can be subdivided into two substates: the running and queued states. When a thread is in the running state, it is assigned CPU cycles and is actually running. When a thread is in the queued state, it is waiting in the queue and competing for its turn to spend CPU cycles. The transition between these two substates is controlled by the virtual machine scheduler.

NOTE: A thread can call the yield() method to voluntarily move itself to the queued state from the running state.

Blocked Threads
The blocked state is entered when one of these events occurs: the thread or another thread calls the suspend() method; the thread calls an object's wait() method; the thread calls the sleep() method; the thread is waiting for an I/O operation to complete; or the thread will join() with another thread.

CPU Cycle Competition
A thread in a blocked state will not be scheduled for running. It will go back to the runnable state, competing for CPU cycles, when the counter-event for the blocking event occurs.

Dead Threads
The dead state is entered when a thread finishes its execution or is stopped by another thread calling its stop() method.

NOTE: The stop method is deprecated.

Boolean Conditions
To avoid the use of stop(), the proper way to exit out of a while (true) loop is to maintain a state variable that is used as the while loop condition check. So, instead of using stop() to halt the thread, you would change the test case to be a boolean condition. Then, when you want the thread to stop, instead of calling stop(), you change the state of the boolean. This causes the thread to stop on the next pass and ensures that the thread does not leave data in an inconsistent state.
//----------------------
boolean done = false;
public void run() {
while(!done) {
....
}
}

public safeStop() {
done = true;
}
//-------------------------

Thread Status
To find out whether a thread is alive-that is, currently runnable or blocked-use the thread's isAlive() method. It will return true if the thread is alive.

NOTE: If a thread is alive, it does not mean it is running, just that it can run.

Thread Synchronization

Introduction
All threads in a program share the same memory space, making it possible for two threads to access the same variable or run the same method of the same object at the same time.

Potential Problems
Problems may occur when multiple threads are accessing the same data concurrently. Threads may race each other, and one thread may overwrite the data just written by another thread. Or, one thread may work on another thread's intermediate result and break the consistency of the data. A mechanism is needed to block one thread's access to the critical data, if the data is being worked on by another thread.

Bank Account Example
Suppose you have a program to handle a user's bank account. There are three subtasks in making a deposit for the user: get the current balance from a remote server, which may take as long as five seconds; add the newly deposited amount into the just-acquired balance; and send the new balance back to the same remote server, which, again, may take as long as five seconds to complete.

Deposit Scenario
If two depositing threads, each making a $1,000 deposit, are started at roughly the same time on a current balance of $1,000, the final balance of these two deposits may reflect the result of only one deposit. In the possible scenario shown here, the balance stored in the remote server increases by only one deposit amount.

Deposit Scenario Program
The program shown here simulates the deposit scenario. An Account class is defined with three methods: getBalance() to fetch the current balance from some pseudo-server, with a simulated five-second delay; setBalance() to write back the new balance to the same pseudo-server, with (again) a simulated five-second delay; and deposit() to use the other two methods to complete a deposit transaction.

Start Deposit Operation
A DepositThread class is declared to start the deposit operation on the account. The main program creates an account instance and then starts two threads to make a deposit of $1,000 each to that account.

Monitor Model
Java uses the idea of monitors to synchronize access to data. A monitor is a guarded place where all the protected resources have the same locks. Only a single key fits all the locks inside a monitor, and a thread must get the key to enter the monitor and access these protected resources.

Monitor Key
If many threads want to enter the monitor simultaneously, only one thread is handed the key; the others must wait outside until the key-holding thread finishes its use of the resources and hands the key back to the Java virtual machine.

NOTE: Deadlock may occur if threads are waiting for each other's key to proceed.

Thread Access
Once a thread gets a monitor's key, the thread can access any of the resources controlled by that monitor countless times, as long as the thread still owns the key. However, if this key-holding thread wants to access the resources controlled by another monitor, the thread must get that particular monitor's key.

Multiple Monitor Keys
At any time, a thread can hold many monitors' keys. Different threads can hold keys for different monitors at the same time.

Protected Resources
In Java, the resources protected by monitors are program fragments in the form of methods or blocks of statements enclosed in curly braces. If some data can be accessed only through methods or blocks protected by the same monitor, access to the data is indirectly synchronized.

synchronized Keyword
You use the keyword synchronized to indicate that the following method or block of statements is to be synchronized by a monitor. When a block of statements is to be synchronized, an object instance enclosed in parentheses immediately following the synchronized keyword is required so the Java virtual machine knows which monitor to check. For example, the deposit() method can be synchronized to allow only one thread to run at a time. The only change needed is a synchronized keyword before the method definition.

Called Object Synchronization
Alternatively, a block of statements in the deposit() method can be synchronized on the called object.

Alternative Program
The output of the alternative program is almost the same, except the first message from the second thread will be interleaved in the messages from the first thread, because the first println() method is not inside the synchronized block.

Unique Key
One unique key will be issued to every object containing a synchronized instance method or being referred by a synchronized block. For synchronized class methods, the key is issued to the class because the method may be called before any class instances exist. This means that every object and every class can have a monitor if there are any synchronized methods or blocks of statements associated with them. Furthermore, a class monitor's key is different from any of the keys of its class instance monitors