JAVA CERTIFICATION EXAM OBJECTIVES
COVERED IN THIS CHAPTER:
4.1 Write code to define, instantiate, and start new threads
using both java.lang.Thread and java.lang.Runnable.
4.2 Recognize the states in which a thread can exist, and
identify ways in which a thread can transition from one state
to another.
4.3 Given a scenario, write code that makes appropriate use
of object locking to protect static or instance variables from
concurrent access problems.
4.4 Given a scenario, write code that makes appropriate use of wait, notify, or notifyAll.
2. Note that calling your thread’s start() method doesn’t immediately cause
the thread to run; it just makes the thread Eligible to run
1. public class CounterThread
extends Thread {
2. public void run() {
3. for (int i = 1; i <= 10; i++) {
4.
System.out.println(“Countin
g: “ + i);
5. }
6. }
7. }
1. CounterThread ct = new
CounterThread();
2. ct.start(); // start(), not run()
1. public class DownCounter
implements Runnable {
2. public void run() {
3. for (int i = 10; i >= 1; i——)
{
4.
System.out.println(“Countin
g Down: “ + i);
5. }
6. }
7. }
1. DownCounter dc = new
DownCounter();
2. Thread t = new Thread(dc);
3. t.start();
Ben Abdallah Helmi Architect J2EE
3. When Execution Ends
When the run() method returns, the
thread has finished its task and is
considered dead.
You can’t restart a dead thread by
calling its start() or run() methods.
You can call other methods (besides
start() and run()) of a dead thread.
Ben Abdallah Helmi Architect J2EE
5. Thread Priorities
Every thread has a priority, which is an integer from 1 to
10; threads with higher priority should get preference
over threads with lower priority. The thread scheduler
considers the priority when it decides which ready
thread should execute. The scheduler generally
chooses the highest-priority waiting thread. If more than
one thread is waiting, the scheduler chooses one of
them. There is no guarantee that the thread chosen will
be the one that has been waiting the longest.
The default priority is 5, but all newly created threads have
their priority set to that of the creating thread. To set a
thread’s priority, call the setPriority() method, passing in
the desired new priority. The getPriority() method
returns a thread’s priority.
Insteadof hard-coding the value 10, the fragment uses the
constant MAX_PRIORITY. The Thread class also
defines constants for MIN_PRIORITY (which is 1) and
NORM_PRIORITY (which is 5). Ben Abdallah Helmi Architect J2EE
6. Daemon Threads
Daemon threads are infrastructure threads, created
automatically by the JVM. The garbage collector is a
daemon thread, and so is the GUI event-processing
thread.
When an application begins to run, there is only one nondaemon thread in existence: the main thread, which
runs your main() method. Any threads created by
daemon threads are initially daemon threads. Threads
created by non-daemon threads are initially nondaemon threads. Before a thread begins execution, you
can change its daemon status by calling its
setDaemon() method, which takes a boolean argument.
The JVM runs until the only live threads are daemons.
In other words, the JVM considers its work to be done
when the only remaining threads are its own
infrastructure threads
Ben Abdallah Helmi Architect J2EE
7. Controlling Threads
Yielding
Suspending and then resuming
Sleeping and then waking up
Blocking and then continuing
Waiting and then being notified
Ben Abdallah Helmi Architect J2EE
8. Yielding
A thread can offer to move out of the
virtual CPU by yielding.
The yield() method is a static method of
the Thread class. It always causes the
currently executing thread to yield.
Yielding allows a time-consuming thread
to permit other threads to execute.
Ben Abdallah Helmi Architect J2EE
9. Suspending
The exact effect of suspend() and
resume() is much better implemented
using wait() and notify().
Ben Abdallah Helmi Architect J2EE
10. Sleeping
A sleeping thread passes time without doing
anything and without using the CPU.
public static void sleep(long milliseconds) throws
InterruptedException Or public static void
sleep(long milliseconds, int nanoseconds) throws
InterruptedException
The Thread class has a method called interrupt().
A sleeping thread that receives an interrupt() call
moves immediately into the Ready state; when it
gets to run, it will execute its InterruptedException
handler
Ben Abdallah Helmi Architect J2EE
11. Blocking
Many methods that perform input or output have to wait
for some occurrence in the outside world before they
can proceed; this behavior is known as blocking. A good
example is reading from a socket:
1. try {
2. Socket sock = new Socket(“magnesium”, 5505);
3. InputStream istr = sock.getInputStream();
4. int b = istr.read();
5. }
6. catch (IOException ex) {
7. // Handle the exception
8. }
Ben Abdallah Helmi Architect J2EE
12. Monitor States
The wait() method puts an executing
thread into the Waiting state, and the
notify() and notifyAll() methods move
waiting threads out of the Waiting
state. However, these methods are
very different from
suspend(), resume(), and yield(). For
one thing, they are implemented in the
Object class, not in Thread. For
another, they can be called only in
synchronized code
Ben Abdallah Helmi Architect J2EE
13. Java’s monitor support addresses
these issues by providing the following
resources:
A lock for each object
The synchronized keyword for
accessing an object’s lock
The wait(), notify(), and notifyAll()
methods, which allow the object to
control client threads
Ben Abdallah Helmi Architect J2EE
14. The Object Lock and
Synchronization
Every object has a lock. At any moment, that lock is
controlled by, at most, one single thread. The lock controls
access to the object’s synchronized code. A thread that wants
to execute an object’s synchronized code must first attempt to
acquire that object’s lock. If the lock is available— that is, if it
is not already controlled by another thread—then all is well. If
the lock is under another thread’s control, then the attempting
thread goes into the Seeking Lock state and becomes ready
only when the lock becomes available. When a thread that
owns a lock passes out of the synchronized code, the thread
automatically gives up the lock. All this lockchecking and
state-changing is done behind the scenes; the only explicit
programming you need to do is to declare code to be
synchronized.
Ben Abdallah Helmi Architect J2EE
15. wait() and notify()
The wait() and notify() methods
provide a way for a shared object to
pause a thread when it becomes
unavailable to that thread and to allow
the thread to continue when
appropriate. The threads themselves
never have to check the state of the
shared object.
Ben Abdallah Helmi Architect J2EE
16.
Both wait() and notify() must be called
in synchronized code. A thread that
calls wait() releases the virtual CPU;
at the same time, it releases the lock.
It enters a pool of waiting
threads, which is managed by the
object whose wait() method got called.
Every object has such a pool.
Ben Abdallah Helmi Architect J2EE
17. 1. public synchronized
String retrieveMessage()
{
2. while (request == false) {
3. try {
4. wait();
5. } catch
(InterruptedException e) {
}
6. }
7. request = false;
8. return message;
9. }
1. public synchronized void
2. storeMessage(String
message) {
3. this.message = message;
4. request = true;
5. notify();
6. }
The notify() method
rbitrarily selects one of
the threads in the
monitor’s waiting pool
and moves it to the
Seeking Lock state.
Eventually that thread
will acquire the mailbox’s
lock and can proceed
with execution.
Ben Abdallah Helmi Architect J2EE
18.
Here are the main points to remember about
wait():
The calling thread gives up the CPU.
The calling thread gives up the lock.
The calling thread goes into the monitor’s
waiting pool.
Here are the main points to remember about
notify():
One arbitrarily chosen thread gets moved
out of the monitor’s waiting pool and into the
Seeking Lock state.
The thread that was notified must reacquire
the monitor’s lock before it can proceed.
Ben Abdallah Helmi Architect J2EE
19. The Class Lock
It is clear by now that every object (that
is, every instance of every class) has a lock.
Every class
also has a lock. The class lock controls access
to all synchronized static code in the class.
Consider
the following example:
class X {
static int x, y;
static synchronized void foo() {
x++;
y++;
}
Ben Abdallah Helmi Architect J2EE
}
20. notifyAll(): Always check the monitor’s state in a while loop rather than
an if statement.
After changing the monitor’s state, call notifyAll() rather than notify().
1. public synchronized
void mixedUpMethod()
{
2. if (i<16 || f>4.3f ||
message.equals(“UHOH”) {
3. try { wait(); } catch
(InterruptedException
e) { }
4. }
5.
6. // Proceed in a way
that changes
state, and then...
7. notify();
8. }
1. public synchronized
void mixedUpMethod()
{
2. while (i<16 || f>4.3f ||
message.equals(“UHOH”) {
3. try { wait(); } catch
(InterruptedException
e) { }
4. }
5.
6. // Proceed in a way
that changes
state, and then...
7. notifyAll();
8. }
Ben Abdallah Helmi Architect J2EE
21. Synchronizing Part of a
Method
1. class StrangeSync {
2. Rectangle rect = new
Rectangle(11, 13, 1100, 1300
);
3. void doit() {
4. int x = 504;
5. int y = x / 3;
6. rect.width -= x;
7. rect.height -= y;
8. }
9. }
perhaps you want to
synchronize only lines 6
and 7, and perhaps you
want a thread attempting to
execute those lines to
synchronize on the lock of
rect, rather than on the lock
of the current executing
object. The way to do this is
shown here:
1. class StrangeSync {
2. Rectangle rect = new
Rectangle(11, 13, 1100, 1300
);
3. void doit() {
4. int x = 504;
5. int y = x / 3;
6. synchronized(rect) {
7. rect.width -= x;
8. rect.height -= y;
9. }
10. }
11. }
Ben Abdallah Helmi Architect J2EE
22.
To synchronize an entire method, using
the lock of the object that owns the
method. To do this, put the synchronized
keyword in the method’s declaration.
To synchronize part of a method, using
the lock of an arbitrary object. Put curly
brackets around the code to be
synchronized, preceded by
synchronized(theArbitraryObject).
To synchronize part of a method, using
the lock of the object that owns the
method. Put curly brackets around the
code to be synchronized, preceded by
synchronized(this).
Ben Abdallah Helmi Architect J2EE