| |
| Throughout its life, a Java thread is in one of several states.
A thread's state indicates what the Thread is doing and what it is
capable of doing at that time of its life: is it running?
Is it sleeping? Is it dead? |
| |
|
| |
| The above diagram illustrates the various states that a
Java thread can be in at any point during its life.
It also illustrates which method calls cause a transition to another
State.
|
| |
| |
| New Thread |
| The following statement creates a new thread but
does not start it, thereby leaving the thread
in the "New Thread" state. |
| Thread myThread = new MyThreadClass(); |
| |
| |
| When a thread is in
the "New Thread" state, it
is merely an empty Thread object. No system resources
have been allocated for it yet. Thus when a thread is
in this state, we can only start the thread or stop it.
Calling any method besides start() or stop() when a thread
is in this state makes no sense and causes an IllegalThreadstateException. |
| |
| |
| Runnable |
| Now consider these two lines of code: |
Thread myThread = new MyThreadClass();
myThread.start(); |
| |
| The start() method
creates the system resources necessary to
run the thread, schedules the thread to run, and calls the
thread's run() method.
At this point the thread is in the "Runnable" state. This state is
called "Runnable" rather
than "Running" because the thread might not
actually be running when it is in this state.
Many computers have a single processor, making it impossible to run
all "Runnable" threads at the same time. So, the Java runtime
system must implement a scheduling scheme that shares the
processor between all "Runnable" threads.
|
| |
| |
| Not Runnable |
| A thread enters the "Not Runnable" state when
one of these four events occurs: |
| 1. Someone invokes its sleep() method. |
| 2. Someone invokes its suspend() method. |
| 3. The thread uses its wait() method to
wait on a condition variable. |
| 4. The thread is blocking on I/O. |
| |
| For example, |
| The bold line in the following code
snippet puts the current thread to sleep for 10 seconds (10,000 milliseconds): |
| |
try
{
Thread.sleep(10000);
} catch (InterruptedException e)
{
} |
| |
| During the 10 seconds that myThread is asleep; even
if the processor becomes available myThread does not run.
After the 10 seconds are up, myThread becomes "Runnable" again
and, if the processor becomes available, runs. |
| |
| If a thread has been put to sleep, then the
specified number of milliseconds must elapse before
the thread becomes "Runnable" again.
Calling resume() on
a sleeping thread has no effect. |
| |
| The following indicates the escape route for every
entrance into the "Not Runnable" state. |
| 1. If a thread has been put to sleep, then the
specified number of milliseconds must elapse. |
| 2. If a thread has been suspended, then someone
must call its resume() method. |
| 3. If a thread is waiting on a condition
variable, whatever object owns the variable must
relinquish it by calling either notify() or notifyAll(). |
| 4. If a thread is blocked on I/O, then the I/O must complete. |
| |
| |
| Dead |
| A thread can die in two ways: either from natural
causes, or by being killed (stopped).
A thread dies naturally when its run() method exits normally.
|
| For example, |
| The while loop in this method is a finite loop--it will
iterate 100 times and then exit. |
| |
public void run()
{
int i = 0;
while (i < 100)
{
i++;
System.out.println("i = " + i);
}
} |
| |
| A thread with this run() method
will die naturally
after the loop and the run() method completes. |
| |
| We can also kill a thread at any time by
calling its stop() method. |
| The following code snippet creates and starts myThread
then puts the current thread to sleep for 10 seconds.
When the current thread wakes up, the bold line in the code segment kills myThread. |
| |
Thread myThread = new MyThreadClass();
myThread.start();
try
{
Thread.sleep(10000);
} catch (InterruptedException e)
{
}
myThread.stop(); |
| |
| The stop() method
throws a ThreadDeath object at the thread to kill it.
Thus when a thread is killed in this manner it dies asynchronously.
The thread will die when it actually receives the ThreadDeath exception. |
| |
| |
| IllegalThreadStateException |
| The runtime system throws an IllegalThreadStateException
when we call a method on a thread and that thread's state
does not allow for that method call. |
| |
| For example, |
| IllegalThreadStateException is
thrown when we invoke
suspend() on a thread that is not "Runnable". |
| |
| |
| The isAlive() Method |
| A final word about thread state: the programming interface for the
Thread class includes a method called isAlive(). |
| The isAlive() method
returns true if the thread has been started and not stopped. |
| Thus, if the isAlive() method
returns false we know that the
thread is either a "New Thread"
or "Dead". |
| If the isAlive() method returns true, we know that the thread
is either "Runnable" or "Not Runnable". |
| We cannot differentiate between a "New Thread" and
a "Dead" thread; nor can we differentiate between a "Runnable" thread
and a "Not Runnable" thread. |
| |
| |
| Thread Priority |
| A thread's priority tells the Java thread scheduler
when this thread should run in relation to other threads. |
| |
| Some points |
| 1. Most computers have only one CPU, thus threads
must share the CPU with other threads. The execution of
multiple threads on a single CPU, in some order, is called
scheduling. The Java runtime supports a very simple, deterministic
scheduling algorithm known as fixed priority scheduling. |
| |
| 2. Each Java thread is given a numeric priority
between MIN_PRIORITY and MAX_PRIORITY (constants defined
in class Thread). At any given time, when multiple threads
are ready to be executed, the thread with the highest priority
will be chosen for execution. Only when that thread stops, or
is suspended for some reason, will a lower priority thread
start executing. |
| |
| 3. Scheduling of the CPU is fully preemptive. If a thread
with a higher priority than the currently executing thread needs
to execute, the higher priority thread is immediately scheduled. |
| |
| 4. The Java runtime will not preempt the currently running
thread for another thread of the same priority. In other words, the
Java runtime does not time-slice. However, the system implementation
of threads underlying the Java Thread class may support time-slicing.
Do not write code that relies on time-slicing. |
| |
5. In addition, a given thread may, at any time, give
up its right to execute by calling the yield() method.
Threads can only yield the CPU to other threads of the
same priority--attempts to yield to a
lower priority thread are ignored. |
| |
| 6. When all the "Runnable" threads in the system
have the same priority, the scheduler chooses the next
thread to run in a simple, non-preemptive, round-robin
scheduling order. |
| |
| |
| Daemon Threads |
| Daemon threads are those that provide a service for
other threads in the system. Any Java thread can be a daemon thread. |