0% found this document useful (0 votes)
24 views

Chapter 4-Introduction To Multithreading

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Chapter 4-Introduction To Multithreading

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Chapter 4: Multithreading

A program can be divided into a number of small processes. Each small process can be
addressed as a single thread (a lightweight process). You can think of a lightweight process as a
virtual CPU that executes code or system calls. You usually do not need to concern yourself with
lightweight processes to program with threads. Multithreaded programs contain two or more
threads that can run concurrently and each thread defines a separate path of execution. This
means that a single program can perform two or more tasks simultaneously. For example, one
thread is writing content on a file at the same time another thread is performing spelling check.

The main thread


When we run any java program, the program begins to execute its code starting from the main
method. Therefore, the JVM creates a thread to start executing the code present in main method.
This thread is called as main thread. Although the main thread is automatically created, you can
control it by obtaining a reference to it by calling currentThread() method.
Two important things to know about main thread are,
 It is the thread from which other threads will be produced.
 main thread must be always the last thread to finish execution.
class MainThread
{
public static void main(String[] args) Name of thread is Thread[MainThread,5,main]
{
Thread t=Thread.currentThread();
t.setName("MainThread");
System.out.println("Name of thread is "+t);
}
}

Life cycle of a Thread

1. New : A thread begins its life cycle in the new state. It remains in this state until the
start() method is called on it.
2. Runnable : After invocation of start() method on new thread, the thread becomes
runnable.
3. Running : A thread is in running state if the thread scheduler has selected it.
4. Waiting : A thread is in waiting state if it waits for another thread to perform a task. In
this stage the thread is still alive.
5. Terminated : A thread enter the terminated state when it complete its task.

1
Jinka University- Department of Computer Science –2014 EC
Thread Priorities
Every thread has a priority that helps the operating system determine the order in which threads
are scheduled for execution. In java thread priority ranges between 1 to 10,
 MIN-PRIORITY (a constant of 1)
 MAX-PRIORITY (a constant of 10)
By default every thread is given a NORM-PRIORITY(5). The main thread always have NORM-
PRIORITY.
Note: Thread priorities cannot guarantee that a higher priority thread will always be executed
first than the lower priority thread. The selection of the threads for execution depends upon the
thread scheduler which is platform dependent.
Thread Class
Thread class is the main class on which Java's Multithreading system is based. Thread class,
along with its companion interface Runnable will be used to create and run threads for utilizing
Multithreading feature of Java.
Constructors of Thread class
1. Thread ( )
2. Thread ( String str )
3. Thread ( Runnable r )
4. Thread ( Runnable r, String str)
You can create new thread, either by extending Thread class or by implementing Runnable
interface. Thread class also defines many methods for managing threads. Some of them are,
Method Description
setName() to give thread a name
getName() return thread's name
getPriority() return thread's priority
isAlive() checks if thread is still running or not
join() Wait for a thread to end
run() Entry point for a thread
sleep() suspend thread for a specified time
start() start a thread by calling run() method
Some Important points to Remember
1. When we extend Thread class, we cannot override setName() and getName() functions,
because they are declared final in Thread class.
2. While using sleep(), always handle the exception it throws.

static void sleep(long milliseconds) throws InterruptedException


Creating a thread
Java defines two ways by which a thread can be created.
 By implementing the Runnable interface.
 By extending the Thread class.

2
Jinka University- Department of Computer Science –2014 EC
Implementing the Runnable Interface
The easiest way to create a thread is to create a class that implements the runnable interface.
After implementing runnable interface , the class needs to implement the run() method, which is
of form,
public void run()
 run() method introduces a concurrent thread into your program. This thread will end
when run() method terminates.
 You must specify the code that your thread will execute inside run() method.
 run() method can call other methods, can use other classes and declare variables just like
any other normal method.
class MyThread implements Runnable
{
public void run()
{
System.out.println("concurrent thread started running..");
}
}
class MyThreadDemo concurrent thread started running..
{
public static void main( String args[] )
{
MyThread mt = new MyThread();
Thread t = new Thread(mt);
t.start();
}
}
To call the run() method, start() method is used. On calling start(), a new stack is provided to
the thread and run() method is called to introduce the new thread into the program.
Note: If you are implementing Runnable interface in your class, then you need to explicitly
create a Thread class object and need to pass the Runnable interface implemented class object as
a parameter in its constructor.
Extending Thread class
This is another way to create a thread by a new class that extends Thread class and create an
instance of that class. The extending class must override run() method which is the entry point
of new thread.
class MyThread extends Thread
{ concurrent thread started running..
public void run()
{
System.out.println("concurrent thread started running..");
}
}
3
Jinka University- Department of Computer Science –2014 EC
Class MyThreadDemo
{
public static void main( String args[] )
{
MyThread mt = new MyThread();
mt.start();
}
}
In this case also, we must override the run() and then use the start() method to run the thread.
Also, when you create MyThread class object, Thread class constructor will also be invoked, as
it is the super class, hence MyThread class object acts as Thread class object.
What if we call run() method directly without using start() method ?
In above program if we directly call run() method, without using start() method,
public static void main( String args[] )
{
MyThread mt = new MyThread();
mt.run();
}
Doing so, the thread won't be allocated a new call stack, and it will start running in the current
call stack, that is the call stack of the main thread. Hence Multithreading won't be there.
Can we Start a thread twice ?
No, a thread cannot be started twice. If you try to do so, IllegalThreadStateException will be
thrown.
public static void main( String args[] )
{
MyThread mt = new MyThread();
mt.start();
mt.start(); //Exception thrown
}
When a thread is in running state, and you try to start it again, or any method try to invoke that
thread again using start() method, exception is thrown.
Joining threads
Sometimes one thread needs to know when other thread is terminating. In java, isAlive() and
join() are two different methods that are used to check whether a thread has finished its
execution or not.
The isAlive() method returns true if the thread upon which it is called is still running otherwise
it returns false.
final boolean isAlive()
But, join() method is used more commonly than isAlive(). This method waits until the thread on
which it is called terminates.
final void join() throws InterruptedException

4
Jinka University- Department of Computer Science –2014 EC
Using join() method, we tell our thread to wait until the specified thread completes its execution.
There are overloaded versions of join() method, which allows us to specify time for which you
want to wait for the specified thread to terminate.
final void join(long milliseconds) throws InterruptedException
The main thread must always be the last thread to finish its execution. Therefore, we can use
Thread join() method to ensure that all the threads created by the program has been terminated
before the execution of the main thread.
Example of isAlive method
public class MyThread extends Thread
{
public void run()
{
System.out.println("r1 ");
r1 true true r1 r2 r2
try {
Thread.sleep(500);
}
catch(InterruptedException ie) { }

System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
t2.start();
System.out.println(t1.isAlive());
System.out.println(t2.isAlive());
}
}

Example of thread without join() method


public class MyThread extends Thread
{
public void run() r1 r1 r2 r2
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}
catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
t2.start();
}
}

5
Jinka University- Department of Computer Science –2014 EC
In this above program two thread t1 and t2 are created. t1 starts first and after printing "r1" on
console thread t1 goes to sleep for 500 ms. At the same time Thread t2 will start its process and
print "r1" on console and then go into sleep for 500 ms. Thread t1 will wake up from sleep and
print "r2" on console similarly thread t2 will wake up from sleep and print "r2" on console. So
you will get output like r1 r1 r2 r2
Example of thread with join() method
public class MyThread extends Thread
{
public void run() r1 r2 r1 r2
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
try{
t1.join(); //Waiting for t1 to finish
}catch(InterruptedException ie){}
t2.start();
}
}
In this above program join() method on thread t1 ensures that t1 finishes it process before thread
t2 starts.

Specifying time with join()


If in the above program, we specify time while using join() with t1, then t1 will execute for that
time, and then t2 will join it.
t1.join(1500);
Doing so, initially t1 will execute for 1.5 seconds, after which t2 will join it.
Synchronization
At times when more than one thread try to access a shared resource, we need to ensure that
resource will be used by only one thread at a time. The process by which this is achieved is
called synchronization. Synchronization is built around an internal entity known as the lock or
monitor. Every object has an lock associated with it. By convention, a thread that needs
consistent access to an object's fields has to acquire the object's lock before accessing them, and
then release the lock when it's done with them. The synchronization keyword in java creates a
block of code referred to as critical section.
General Syntax :
synchronized (object)
{
6
Jinka University- Department of Computer Science –2014 EC
//statement to be synchronized
}
Every Java object with a critical section of code gets a lock associated with the object. To enter
critical section a thread need to obtain the corresponding object's lock.
Why we use Syncronization ?
If we do not use syncronization, and let two or more threads access a shared resource at the same
time, it will lead to distorted results.
Consider an example, Suppose we have two different threads T1 and T2, T1 starts execution and
save certain values in a file temporary.txt which will be used to calculate some result when T1
returns. Meanwhile, T2 starts and before T1 returns, T2 change the values saved by T1 in the file
temporary.txt (temporary.txt is the shared resource). Now obviously T1 will return wrong result.
To prevent such problems, synchronization was introduced. With synchronization in above case,
once T1 starts using temporary.txt file, this file will be locked(LOCK mode), and no other thread
will be able to access or modify it until T1 returns.
Using Synchronized Methods
Using Synchronized methods is a way to accomplish synchronization. But lets first see what
happens when we do not use synchronization in our program.
Example with no Synchronization
class First
{
public void display(String msg)
{
System.out.print ("["+msg); [welcome [ new [ programmer] ] ]
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;

7
Jinka University- Department of Computer Science –2014 EC
start();
}
public void run()
{
fobj.display(msg);
}
}
public class Syncro
{
public static void main (String[] args)
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second (fnew,"new");
Second ss2 = new Second(fnew, "programmer");
}
}
In the above program, object fnew of class First is shared by all the three running threads(ss, ss1
and ss2) to call the shared method(void display). Hence the result is unsynchronized and such
situation is called Race condition.
Synchronized Keyword
To synchronize above program, we must synchronize access to the shared display() method,
making it available to only one thread at a time. This is done by using keyword synchronized
with display() method.
synchronized void display (String msg)
Using Synchronized block
If you have to synchronize access to an object of a class or you only want a part of a method to
be synchronized to an object then you can use synchronized block for it.
class First
{
public void display(String msg)
{
System.out.print ("["+msg); [welcome] [new] [programmer]
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}

8
Jinka University- Department of Computer Science –2014 EC
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
start();
}
public void run()
{
synchronized(fobj) //Synchronized block
{
fobj.display(msg);
}
}
}
public class Syncro
{
public static void main (String[] args)
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second (fnew,"new");
Second ss2 = new Second(fnew, "programmer");
}
}
Because of synchronized block this program gives the expected output.

Example 2: Understanding the problem without Synchronization

In this example, there is no synchronization, so output is inconsistent. Let's see the example:

class Table{
void printTable(int n){//method not synchronized
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
} } }

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}
Output:
5 9
Woldia University- Department of Computer S cience100
--2012
10
200
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
} }

class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}

Java synchronized method


If you declare any method as synchronized, it is known as synchronized method. Synchronized
method is used to lock an object for any shared resource. When a thread invokes a synchronized
method, it automatically acquires the lock for that object and releases it when the thread
completes its task.

Example of java synchronized method

class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
} } }

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}

10
Woldia University- Department of Computer Science --2012
public void run(){
t.printTable(5);
}

class MyThread2 extends Thread{


Table t; Output: 5
10
MyThread2(Table t){ 15
this.t=t; 20
} 25
public void run(){ 100
t.printTable(100); 200
300
} 400
} 500

public class TestSynchronization2{


public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}

Difference between synchronized keyword and synchronized block


When we use synchronized keyword with a method, it acquires a lock in the object for the whole
method. It means that no other thread can use any synchronized method until the current thread,
which has invoked it's synchronized method, has finished its execution.
Synchronized block acquires a lock in the object only between parentheses after the
synchronized keyword. This means that no other thread can acquire a lock on the locked object
until the synchronized block exits. But other threads can access the rest of the code of the
method.
Which is more preferred - Synchronized method or Synchronized block?
In Java, synchronized keyword causes a performance cost. A synchronized method in Java is
very slow and can degrade performance. So we must use synchronization keyword in java when
it is necessary else, we should use Java synchronized block that is used for synchronizing critical
section only.
Interthread Communication
Java provide benefits of avoiding thread pooling using inter-thread communication. The wait(),
notify(), and notifyAll() methods of Object class are used for this purpose. These method are
implemented as final methods in Object, so that all classes have them. All the three method can
be called only from within a synchronized context.

11
Woldia University- Department of Computer Science --2012
 wait() tells calling thread to give up monitor and go to sleep until some other thread
enters the same monitor and call notify.
 notify() wakes up a thread that called wait() on same object.
 notifyAll() wakes up all the thread that called wait() on same object.

Difference between wait() and sleep()

wait() sleep()
called from synchronized block no such requirement
monitor is released monitor is not released
gets awake when notify() or does not get awake when notify() or notifyAll() method
notifyAll() method is called. is called
not a static method static method
wait() is generally used on condition sleep() method is simply used to put your thread on
sleep.
Thread Pooling
Pooling is usually implemented by loop i.e to check some condition repeatedly. Once condition
is true appropriate action is taken. This waste CPU time.
Deadlock

Deadlock is a situation of complete Lock, when no thread can complete its execution because
lack of resources. In the above picture, Thread 1 is holding a resource R1, and need another
resource R2 to finish execution, but R2 is locked by Thread 2, which needs R3, which in turn is
locked by Thread 3. Hence none of them can finish and are stuck in a deadlock.

Example of deadlock
class Pen{}
12
Woldia University- Department of Computer Science --2012
class Paper{}
public class Write {
public static void main(String[] args)
{
final Pen pn =new Pen();
final Paper pr =new Paper();
Thread t1 = new Thread(){
public void run()
{
synchronized(pn)
{
System.out.println("Thread1 is holding Pen");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
synchronized(pr)
{ System.out.println("Requesting for Paper");
}
}
}
};
Thread t2 = new Thread(){
public void run()
{
synchronized(pr) {
System.out.println("Thread2 is holding Paper");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
synchronized(pn)
{ System.out.println("requesting for Pen"); }
}
}
};
t1.start();
t2.start();
}
}

Thread1 is holding Pen Thread2 is holding Paper

13
Woldia University- Department of Computer Science --2012

You might also like