MultiThreadedProgramming
MultiThreadedProgramming
Programming
multithreaded programming
multithreaded programming
• Java provides built-in support for multithreaded programming. A
multithreaded program contains two or more parts that can run
concurrently. Each part of such a program is called a thread, and each
thread defines a separate path of execution. Thus, multithreading is a
specialized form of multitasking.
• There are two distinct types of multitasking: process-based and
thread-based.
multithreaded programming
• A process is, in essence, a program that is executing.
• Thus, process-based multitasking is the feature that allows your
computer to run two or more programs concurrently. For example,
process-based multitasking enables you to run the Java compiler at
the same time that you are using a text editor or visiting a web site. In
process-based multitasking, a program is the smallest unit of code
that can be dispatched by the scheduler.
multithreaded programming
• In a thread-based multitasking environment, the thread is the
smallest unit of dispatchable code. This means that a single program
can perform two or more tasks simultaneously. For instance, a text
editor can format text at the same time that it is printing, as long as
these two actions are being performed by two separate threads.
• Thus, process-based multitasking deals with the “big picture,” and
thread-based multitasking handles the details.
multithreaded programming
• Multitasking threads require less overhead than multitasking
processes.
• Processes are heavyweight tasks that require their own separate
address spaces.
• Interprocess communication is expensive and limited. Context
switching from one process to another is also costly.
multithreaded programming
• Threads, on the other hand, are lighter weight.
• They share the same address space and cooperatively share the same
heavyweight process.
• Interthread communication is inexpensive, and context switching
from one thread to the next is lower in cost.
• While Java programs make use of process-based multitasking
environments, process-based multitasking is not under Java’s direct
control.
• However, multithreaded multitasking is.
multithreaded programming
• Multithreading enables you to write efficient programs that make
maximum use of the processing power available in the system.
• One important way multithreading achieves this is by keeping idle
time to a minimum.
• This is especially important for the interactive, networked
environment in which Java operates because idle time is common.
• Multithreading helps you reduce this idle time because another
thread can run when one is waiting.
multithreaded programming
• Threads exist in several states.
• A thread can be running. It can be ready to run as soon as it gets CPU
time.
• A running thread can be suspended, which temporarily halts its
activity. A suspended thread can then be resumed, allowing it to pick
up where it left off.
• A thread can be blocked when waiting for a resource. At any time, a
thread can be terminated, which halts its execution immediately.
• Once terminated, a thread cannot be resumed.
multithreaded programming
• Java assigns to each thread a priority that determines how that thread
should be treated with respect to the others. Thread priorities are
integers that specify the relative priority of one thread to another. As
an absolute value, a priority is meaningless; a higher-priority thread
doesn’t run any faster than a lower-priority thread if it is the only
thread running.
• Instead, a thread’s priority is used to decide when to switch from one
running thread to the next. This is called a context switch. The rules
that determine when a context switch takes place are simple:
multithreaded programming
• A thread can voluntarily relinquish control. This occurs when explicitly
yielding, sleeping, or when blocked. In this scenario, all other threads
are examined, and the highest-priority thread that is ready to run is
given the CPU.
• A thread can be preempted by a higher-priority thread. In this case, a
lower-priority thread that does not yield the processor is simply
preempted —no matter what it is doing—by a higher-priority thread.
Basically, as soon as a higher-priority thread wants to run, it does. This
is called preemptive multitasking.
multithreaded programming
• New Thread creation: When a program calls the start() method, a new
thread is created and then the run() method is executed. But if we
directly call the run() method then no new thread will be created and
run() method will be executed as a normal method call on the current
calling thread itself and no multi-threading will take place.
• Example Program
• As we can see in the above example, when we call the start() method
of our thread class instance, a new thread is created with default
name Thread-0 and then run() method is called and everything inside
it is executed on the newly created thread.
multithreaded programming
• Now, let us try to call run() method directly instead
of start() method:
• Example Program
• As we can see in the above example, when we called
the run() method of our MyThread class, no new thread
is created and the run() method is executed on the
current thread i.e. main thread. Hence, no multi-
threading took place. The run() method is called as a
normal function call.
multithreaded programming
• Multiple invocation: In Java’s multi-threading
concept, another most important difference
between start() and run() method is that we can’t call
the start() method twice otherwise it will throw
an IllegalStateException whereas run() method can be
called multiple times as it is just a normal method
calling.
• As we can see in the above example,
calling run() method twice doesn’t raise any exception
and it is executed twice as expected but on
the main thread itself.
multithreaded programming
• How can one thread know when another thread
• Two ways exist to determine whether a thread has finished. First, you can call
• isAlive( ) on the thread. This method is defined by Thread, and its general
form is shown here:
• final boolean isAlive( ) has ended?
• The isAlive( ) method returns true if the thread upon which it is called is still
• running. It returns false otherwise.
• While isAlive( ) is occasionally useful, the method that you will more
• commonly use to wait for a thread to finish is called join( ), shown here:
• final void join( ) throws InterruptedException
multithreaded programming
• This method waits until the thread on which it is called terminates. Its name
comes from the concept of the calling thread waiting until the specified thread
joins it. Additional forms of join( ) allow you to specify a maximum amount
of
time that you want to wait for the specified thread to terminate.
• Here is an improved version of the preceding example that uses join( ) to
ensure that the main thread is the last to stop.
Synchronization
• When two or more threads need access to a shared resource, they need
some way to ensure that the resource will be used by only one thread at
a time. The process by which this is achieved is called synchronization.
Java provides unique, language-level support for it.
• Key to synchronization is the concept of the monitor. A monitor is an
object that is used as a mutually exclusive lock. Only one thread can
own a monitor at a given time. When a thread acquires a lock, it is said
to have entered the monitor. All other threads attempting to enter the
locked monitor will be suspended until the first thread exits the monitor.
These other threads are said to be waiting for the monitor. A thread that
owns a monitor can re-enter the same monitor if it so desires.
Synchronization
• To understand the need for synchronization, let’s begin with a simple
example that does not use it—but should. The following program has
three simple classes.
• The first one, Callme, has a single method named call( ).
• The call( ) method takes a String parameter called msg. This method
tries to print the msg string inside of square brackets.
• The interesting thing to notice is that after call( ) prints the opening
bracket and the msg string, it calls Thread.sleep(1000), which pauses
the current thread for one second.
Synchronization
• The constructor of the next class, Caller, takes a reference to an
instance of the Callme class and a String, which are stored in target
and msg, respectively.
• The constructor also creates a new thread that will call this object’s
run( ) method. The run( ) method of Caller calls the call( ) method on
the target instance of Callme, passing in the msg string.
• Finally, the Synch class starts by creating a single instance of Callme,
and three instances of Caller, each with a unique message string. The
same instance of Callme is passed to each Caller.
Gaurded Blocks
• Threads often have to coordinate their actions. The most common
coordination idiom is the guarded block. Such a block begins by
polling a condition that must be true before the block can proceed.
There are a number of steps to follow in order to do this correctly.
• Why is this version of guardedJoy synchronized? Suppose d is the object we're using to invoke
wait. When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error is
thrown. Invoking wait inside a synchronized method is a simple way to acquire the intrinsic lock.
• When wait is invoked, the thread releases the lock and suspends execution. At some future time,
another thread will acquire the same lock and invoke Object.notifyAll, informing all threads
waiting on that lock that something important has happened:
Guarded Blocks
• public synchronized notifyJoy() {
• joy = true;
• notifyAll();
•}
• Some time after the second thread has released the lock, the first thread
reacquires the lock and resumes by returning from the invocation of wait.
• There is a second notification method, notify, which wakes up a single thread.
Because notify doesn't allow you to specify the thread that is woken up, it is
useful only in massively parallel applications — that is, programs with a large
number of threads, all doing similar chores. In such an application, you don't
care which thread gets woken up.
Polling
• The process of testing a condition repeatedly till it becomes true is known as
polling.
• Polling is usually implemented with the help of loops to check whether a
particular condition is true or not. If it is true, certain action is taken. This
waste many CPU cycles and makes the implementation inefficient.
• For example, in a classic queuing problem where one thread is producing
data and other is consuming it.
• To avoid polling, Java uses three methods, namely, wait(), notify() and
notifyAll().
• All these methods belong to object class as final so that all classes have
them. They must be used within a synchronized block only.
Polling
• wait()-It tells the calling thread to give up the lock and go to sleep
until some other thread enters the same monitor and calls notify().
• notify()-It wakes up one single thread that called wait() on the same
object. It should be noted that calling notify() does not actually give
up a lock on a resource.
• notifyAll()-It wakes up all the threads that called wait() on the same
object.
Wait and notify
Wait() Notify()
When wait() is called on a thread holding the When the notify() is called on a thread holding
monitor lock, it surrenders the monitor lock and the monitor lock, it symbolizes that the thread is
enters the waiting state. soon going to surrender the lock.