Pages

Multithreading in JAVA

What is Thread?

            The running program of computer is known as process. A thread is a lightweight sub process, a smallest unit of processing. It is a separate path of execution. It shares the memory area of process.
There can be multiple processes inside the OS and one process can have multiple threads.

Single Process
Thread - 0 Thread - 1

Operation - 1

  Operation - 1 

Operation - 2
   ..................

 Operation - 2
   ....................

 Operation - N
   ..................

Operation - N
   ...................


Multithreading

A flow of control is known as thread. If a program contains multiple flow of controls for achieving concurrent execution then is known as multi threaded program. A program is said to be a multi threaded program if and only if in which there exist 'n' number of sub-programs there exist a separate flow of control. All such flow of controls are executing concurrently such flow of controls are known as threads and such type of applications or programs is called multi threaded programs.
Multithreading is a process of executing multiple threads simultaneously. Thread is basically a lightweight sub - process, a smallest unit of processing. Thread don't allocate separate memory area so save memory, switching between the threads takes less time than processes. Multithreading is mostly used in games, animations etc.


Multiprocessing Vs Multithreading


Multi - processing Multi - threading
It is the one in which there exist single flow of control. It is the one in which there exist multiple flow of controls.
Each process have its own address in memory i.e. each process allocates seperate memory area. Threads share the same address space. At least one process is required for each thread.
Cost of communication between the process is high. Cost of communication between the process is low.
Switching from one process to another require some time and loading registers, memory maps, updating lists etc. Context switch is very less.
Process is heavy weight. Thread is lightweight.


Life cycle of a Thread (Thread States)

All the threads will undergo different types of states. In JAVA for a thread we have five states. They are new , ready, running, waiting and halted or deadstate.
  • New state: It is one in which the thread about to enter into main memory.
  • Ready state: It is one in which the thread is entered into memory space allocated and it is waiting for                       CPU for executing.
  • Running state: A state is said to be a running state if and only if the thread is under the control of CPU.
  • Waiting state: It is one in which the thread is waiting because of the following factors:
    1. For the repeating CPU brust time of the thread (CPU brust time is an amount of time required by the thread by the CPU).
    2. Make the thread to sleep for sleep for some specified amount of time.
    3. Make the thread to suspend.
    4. Make the thread to wait for a period of time.
    5. Make the thread to wait without specifying waiting time.
  • Halted state: It is one in which the thread has completed its total execution. As long as the thread is in new and halted states whose execution status is false where as when the thread is in ready, running and waiting states the execution states is true.


                                                       fig: Thread Life cycle



How to create Thread in JAVA?

There are two ways to create a thread:
  1. By extending Thread class.
  2. By implementing Runnable interface.

By extending Thread class

/Thread class provide constructors and methods to create and perform operations on a thread. Thread class extends Object class and implements Runnable interface. An object of Thread class can be created in three ways. They are:

  1. Directly --->         Thread t = new Thread ();
  2. Using factory method --->        Thread t1 = Thread.currentThread ();
  3. Using sub-class of Thread class --->
                                                            class C1 extends Thread{
                                                                                                    ..............;
                                                                                                    ..............;
                                                                                                   };
                                                                C1 ob = new C1 ();
                                                                Thread t1 = new C1 ();

    Here, C1 is the sub-class of thread class

Commonly used Constructors of Thread class


  • Thread (): With this Constructor we can create an object of the Thread class whose default thread                        name is thread-0.
                     For example:
                                           Thread t = new Thread ();
                                           System.out.println(t.getName ());  //Thread - 0
  • Thread (String name): This Constructor is used for creating a thread and we can give the user                                               specified name.
                                      For example:
                                                           Thread t = new Thread ("mythread");
  • Thread (Runnable r): This Constructor is used for converting Runnable object into Thread object for                                    entering into run method of Runnable interface by making use of start method of                                  Thread class without giving thread name.
  • Thread (Runnable r, String s): This Constructor is similar to above Constructor but we give thread                                           name through this Constructor.


By implementing Runnable interface

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. Runnable interface have only one method named run ().

  • public void run (): It is used to perform action for a thread.
  • public void start (): It is used to start newly created thread.

Commonly used methods of Thread class



  • public void run (): It is used to perform action for a thread . Any JAVA programmer wants to define a logic for the thread that logic must be defined only run () method. When the thread is started, the JVM  looks for the appropriate run () method for executing the logic of the thread. Thread class is a concrete class and it contains all defined methods. run () method is by default contains a definition with null body. Since we are providing the logic for the thread in run () method. Hence it must be overridden by extending Thread class into out own class.


          For example:

                        class C1 extends Thread
                        {
                                public void run ()
                                {
                                        ...................... ;
                                        ...................... ;
                                }
                         };

  • public void start (): It starts the execution of the thread. JVM calls the run () method of the thread.


          For example:
               
                     Thread t1 = new Thread();
                     t1.start ();
                     Thread t2 = Thread.currentThread ();
                      t2.start ();


Example by extending Thread class

class Multi extends Thread
{
public void run() {
System.out.println("thread is running....");
}

public static void main(String[] args) {
Multi m1 = new Multi();
m1.start();
}
}


Example by implementing the Runnable interface

class ThreadDemo implements Runnable
{
public void run() {
System.out.println("Thread is running....");
}

public static void main(String[] args) {
ThreadDemo t1 = new ThreadDemo();
Thread th = new Thread (t1);
th.start();
}

}



If you are not extending the Thread class, your class object would not be treated as  a thread object. So you need to explicitly create Thread class object. We are passing the object of your class that implements Runnable so that your class run () method may execute.

Can we start a thread twice?
After starting a thread, it can never br started again. If you does so, an IllegalThreadStateException is thrown.

Example to start Thread Twice

class Multi extends Thread
{
public void run() {
System.out.println("thread is running....");
}

public static void main(String[] args) {
Multi m1 = new Multi();
m1.start();
                m1.start();
}

}


What if we call run () method directly instead start () method?

Each thread starts in a separate call stack. Invoking the run () method from main thread, the run () method goes onto the current call stack rather than at the beginning of a new call stack.


Example to call directly run () method

class MultiThread extends Thread
{
public void run() {
System.out.println("Thread is running...");
}

public static void main(String [] args) {
MultiThread t1 = new MultiThread();
t1.run(); //fine but does not start a separate call stack
}

}


  • public void sleep (long miliseconds): It causes the currently executing thread to sleep (temporarily                                                                cease execution) for the specified number of milliseconds.


Example of sleep () in Thread class


class ThreadDemo1 extends Thread
{
public void run() {
for (int i=1; i<5 ; i++ )
{
try
{
Thread.sleep(300);
}
catch (InterruptedException e)
{
System.out.println(e);
}
System.out.println(i);
}
}

public static void main(String[] args) {
ThreadDemo1 t1 = new ThreadDemo1();
ThreadDemo1 t2 = new ThreadDemo1();

t1.start();
t2.start();
}
}




  • public boolean isAlive (): It tests if the thread is alive.

Program to display 1 to 10 after each & every 1 seconds 



class Th extends Thread
{
public void run() {
try
{
for (int i=1; i<=10 ; i++ )
{
System.out.println("Value of i = " +i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println(e);
}
}
}

class ThreadDemo8
{
public static void main(String[] args) {
Th1 t1 = new Th1();
System.out.println("Is t1 alive before start = " +t1.isAlive());
t1.start();
System.out.println("Is t1 alive after start = " +t1.isAlive());
}



  • public void join (): This method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task.
          syntax:
                     public void join () throws InterruptedException
                     public void join (long milliseconds) throws InterruptedException

Example of join (long milliseconds) method


class ThreadDemo10 extends Thread
{
public void run() {
for (int i=1; i<=5 ; i++ )
{
try
{
Thread.sleep(500);
}
catch (Exception e)
{
System.out.println(e);
}
System.out.println(i);
}
}

public static void main(String[] args) {
ThreadDemo10 t1 = new ThreadDemo10();
ThreadDemo10 t2 = new ThreadDemo10();
ThreadDemo10 t3 = new ThreadDemo10();

t1.start();
try
{
t1.join();
}
catch (Exception e)
{
System.out.println(e);
}
t2.start();
t3.start();
}
}

Note: In the above example, when t1 is completes its task for 1500 milliseconds (3 times) then t2 and t3                 starts executing.



  • public String getName (): It returns the name of the thread.
  • public void setName (String name): It changes the name of the thread.
  • public int getId (): It returns the Id of the thread.
Example of getName (), setName (String) & getId () methods


class ThreadDemo11 extends Thread
{
public void run() {
System.out.println("running...");
}

public static void main(String[] args) {
ThreadDemo11 t1 = new ThreadDemo11();
ThreadDemo11 t2 = new ThreadDemo11();
System.out.println("Name of t1: " +t1.getName());
System.out.println("Name of t2: " +t2.getName());
System.out.println("ID of t1: "+t1.getId());
t1.start();
t2.start();
t1.setName("hungry4java.blogspot.com");
System.out.println("After changing name of t1: "+t1.getName());
}
}




  • public Thread currentThread (): This method returns a reference to the currently executing thread                                                         object.
           Syntax: 
                        public static Thread currentThread ();

Example of currentThread () method


class ThreadDemo12 extends Thread
{
public void run() {
System.out.println(Thread.currentThread().getName());
}

public static void main(String[] args) {
ThreadDemo12 t1 = new ThreadDemo12();
ThreadDemo12 t2 = new ThreadDemo12();

t1.start();
t2.start();
}
}



The Thread Scheduler

The Thread Scheduler is the part of the JVM that decides which thread run. There is no guarantee that which runnable thread will be chosen to run by the thread scheduler. The thread scheduler mainly uses preemptive or time slicing scheduling to schedule the threads.


Difference between preemptive scheduling and time slicing

Under preemptive scheduling, the highest priority task executes until it enters the waiting or dead states or a higher priority task comes into existance. Under time slicing, a task executes for a predefined slice of time and then re-enters the pool of ready tasks. The scheduler then determines which task should execute next, based on priority and other factors.

public int getPriority (): It returns the priority of thread.
public int setPriority (int priority): It changes the priority of the thread.

Each thread has a priority. Priorities are represented by a number between 1 and 10. In most cases, thread scheduler schedules the threads according to their priority (known as preemptive scheduling). But it is not guaranteed because it depends on JVM specification that which scheduling it chooses.

Three constants defined in Thread class
  • public static int MIN_PRIORITY
  • public static int NORM_PRIORITY
  • public static int MAX_PRIORITY
Default priority of a thread is 5(NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.

Example of Priority of a Thread

class ThreadDemo13 extends Thread
{
public void run() {
System.out.println("running thread name is: "+Thread.currentThread().getName());
System.out.println("running thread priority is: "+Thread.currentThread().getPriority());
}

public static void main(String[] args) {
ThreadDemo13 t1 = new ThreadDemo13();
ThreadDemo13 t2 = new ThreadDemo13();

t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}



Daemon Thread

Daemon thread in java are those which runs in background and mostly created by JVM for performing background task like Garbage collection and other house keeping tasks. In one line main difference between daemon thread and user thread is that as soon as all user thread finish execution java program of JVM terminates itself, JVM doesn't wait for daemon thread to finish their execution. As soon as last non daemon thread finished JVM terminates no matter how many Daemon thread exist or running inside JVM.

Methods for Daemon Thread

  • public final boolean isDaemon (): Tests if this thread is a daemon thread and it returns true if this                                                              thread is a daemon thread otherwise returns false.
  • public final void setDaemon (boolean on): Marks this thread as either a daemon thread or a user                                                                         thread.

Example of Daemon Thread

class MyThread extends Thread
{
public void run() {
System.out.println("Name: "+Thread.currentThread().getName());
System.out.println("Daemon: "+Thread.currentThread().isDaemon());
}

public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setDaemon(true);
t1.start();
t2.start();
}
}



Synchronization in Thread

It is the process of allowing only one thread at a time among 'n' number of threads into that area which is sharable to perform write operation. If anything (either data members or methods or objects or classes) is sharable then we must apply the concept of synchronization.
Let us assume that there is a shareable variable called balance whose initial value is zero. There are two threads t1 and t2 repectively. t1 and t2 want to update the balance variable with their respective values i.e, 10 and 20 at the same time. After completion of these two threads the final value in the balance is either 10 or 20 but not 30 which is the inconsistent result.
To achieve the consistent result we must apply the concept of synchronization. When we apply synchronization concept on the above scenario, when two threads are started at same time, the first thread which is started is given a chance to update balance variable with its respective value. When second thread is trying to access the balance variable value JVM makes the second thread to wait until first thread completes its execution by locking balance variable value.
After completion of first thread the value in the balance is 10 and second thread will be allowed to update balance variable value. After completion of second thread the value of the balance is 30, which is the consistent result. Hence, in synchronization locking and unlocking is  taking place until all the threads are completed their execution. Synchronization is the capability of control the access of multiple threads to any shared resource.


Synchronization Techniques:

In JAVA we have two types of synchronization techniques. They are
  1. synchronized method
  2. synchronized blocks

1. Synchronized methods:

If you declare any method as synchronized, it is known as synchronized method. If any method is sharable for 'n' number of threads the make the method as synchronized by using a keyword synchronized. 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 method returns. In JAVA we have two types of synchronized methods. They are
  1. synchronized Instance Methods and
  2. synchronized static methods
a. Synchronized Instance methods
            Syntax:
                    synchronized <return type> method name (method parameter if any)
                    {
                        Block statements;
                     }

b. Synchronized static method
               Syntax:
                       synchronized static <return type> method name (method parameter if any)
                       {
                              Block statements;
                        }

Example without Synchronization


class Table
{
void printTable(int n) //method is 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 Demo1 extends Thread
{
Table t;
Demo1(Table t) {
this.t = t;
}

public void run() {
t.printTable(5);
}
}

class Demo2 extends Thread
{
Table t;
Demo2(Table t) {
this.t = t;
}

public void run() {
t.printTable(100);
}
}

class MyThread2
{
public static void main(String[] args) {
Table obj = new Table(); //only one object
Demo1 d1 = new Demo1(obj);
Demo2 d2 = new Demo2(obj);
d1.start();
d2.start();
}
}


Example with synchronization


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 Demo1 extends Thread
{
Table t;
Demo1(Table t) {
this.t = t;
}

public void run() {
t.printTable(5);
}
}

class Demo2 extends Thread
{
Table t;
Demo2(Table t) {
this.t = t;
}

public void run() {
t.printTable(100);
}
}

class MyThread3
{
public static void main(String[] args) {
Table obj = new Table(); //only one object
Demo1 d1 = new Demo1(obj);
Demo2 d2 = new Demo2(obj);
d1.start();
d2.start();
}
}


2. Synchronized Block

Synchronized block can be used to perform synchronization on any specific resource of the method. Suppose you have 50 lines of code in your method, but you want to synchronize onyl 5 lines, you can use synchornized block. If you put all the codes of the method in the synchronized block, it will work same as the synchronized method

Syntax:
synchronized (object of current class)
{
   Block of statement(s);
}

Note: Synchronized block is used to lock an object for any shared resource. Scope of synchronized block is smaller than the method.

synchronized (object reference expression)
{
   //code block
}

Example of Synchronized Block


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

class Demo1 extends Thread
{
Table t;
Demo1(Table t) {
this.t = t;
}

public void run() {
t.printTable(5);
}
}

class Demo2 extends Thread
{
Table t;
Demo2(Table t) {
this.t = t;
}

public void run() {
t.printTable(100);
}
}

class MyThread4
{
public static void main(String[] args) {
Table obj = new Table(); //only one object
Demo1 d1 = new Demo1(obj);
Demo2 d2 = new Demo2(obj);
d1.start();
d2.start();
}
}



Deadlock

Deadlock can occur in a situation when a thread is waiting for an object lock, that is acquired by another thread and second thread is waiting for an object lock that is acquired by first thread. Since, both threads are waiting for each other to release the lock, the condition is called deadlock.



Example of Deadlock in JAVA

public class Deadlock
{
public static void main(String[] args) {
final String resource1 = "Abhishek jha";
final String resource2 = "Vikash kumar";
//t1 tries to lock resource1 then resource2

Thread t1 = new Thread() {
public void run() {
synchronized(resource1) {
System.out.println("Thread 1: locked resource1");
try
{
Thread.sleep(100);
}
catch (Exception e)
{
}
synchronized(resource2) {
System.out.println("Thread 1: Locked resource2");
}
}
}
};
//t2 tries to lock resource2 the resource1
Thread t2 = new Thread() {
public void run() {
synchronized(resource2) {
System.out.println("Thread 2: locked resource2");
try
{
Thread.sleep(100);
}
catch (Exception e)
{
}
synchronized(resource1) {
System.out.println("Thread2: locked resource1");
}
}
}
};

t1.start();
t2.start();
}
}



Inter - thread communication (Cooperation)

Inter - thread communication (Cooperation) is all about making synchronized threads communicate with each other. Cooperation is a mechanism in which a thread is paused running in its critical section and another thread is allowed to enter (or lock) in the same critical section to be executed. It is implemented by following methods of Object class:
  1. wait ()
  2. notify ()
  3. notifyAll ()

i. wait () method

Causes current thread to release the lock and wait until either another thread invokes the notify () method or the notifyAll () method for this object, or a specified amount of time has elapsed. The current thread must own this object's monitor.
Syntax:
            public final void wait () throws InterruptedException
            public final void wait (long timeout) throws InterruptedException

ii. notify () method

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.

iii. notifyAll () method

Wakes up all threads that are waiting on this object's monitor
Syntax:
            public final void notifyAll ()


Example of Inter Thread Communication

class Customer
{
int amount = 0;
int flag = 0;
public synchronized int withdraw(int amount) {
System.out.println(Thread.currentThread().getName()+" is going to withdraw");
if(flag == 0) {
try
{
System.out.println("Waiting....");
wait();
}
catch (Exception e)
{
}
}
this.amount -= amount;
System.out.println("withdraw completed");
return amount;
}

public synchronized void deposite(int amount) {
System.out.println(Thread.currentThread().getName()+" is going to deposite");
this.amount += amount;
System.out.println("deposit completed");
flag=1;
notifyAll();
}
}

class SynMethod
{
public static void main(String[] args) {
final Customer c = new Customer();

Thread t1 = new Thread() {
public void run() {
c.withdraw(5000);
System.out.println("After withdraw amount is "+c.amount);
}
};
Thread t2 = new Thread() {
public void run() {
c.deposite(9000);
System.out.println("After deposit amount is "+c.amount);
}
};
t1.start();
t2.start();
}
}


Interrupting a Thread

If any thread is in sleeping or waiting state (i.e sleep () or wait () is invoked), calling the interrupt () method on the thread, breaks out the sleeping or waiting state throwing InterruptedException. If the thread is not in the sleeping or waiting state, calling the interrupt () method performs normal behaviour and doesn't interrupt the thread but sets the interrupt flag to true.

Methods provided by the Thread class for interrupting a thread

  • public void interrupt ()
  • public static boolean interrupted ()
  • public boolean isInterrupted ()

Example of Interrupting a Thread that stop working

class A extends Thread
{
public void run() {
try
{
System.out.println("Task.......");
Thread.sleep(800);
System.out.println("task");
}
catch (InterruptedException e)
{
throw new RuntimeException("Thread interrupted "+e);
}
}
public static void main(String[] args) {
A t1 = new A();
t1.start();
try
{
t1.interrupt();
}
catch (Exception e)
{
System.out.println("Exception handled "+e);
}
}
}



Runtime class

Runtime is a predefined class present in java.lang package. Runtime class encapsulates the java runtime environment. It is not possible for programmer to instantiate the Runtime class (never call constructor) through constructor. If the programmer wants to construct the object of the Runtime class, the programmer have to call a static method of the Runtime class.

  • public static Runtime getRuntime (): It returns the object of Runtime class;
  • public long totalMemory (): To find out the total memory available in the JVM occupied memory                                                    space.
  • public long freeMemory (): To find total memory available for JVM occupied memory space.
  • public gc (): To call the garbage collector explicitly to halt the execution.
  • public void exit (int level):  If you pass 0 as argument normal termination of child process. But any                                                other integer as arguments.

Example of Runtime class

class RuntimeDemo
{
public static void main(String[] args) throws Exception
{
Runtime rt = Runtime.getRuntime ();
System.out.println(rt.freeMemory ());
System.out.println(rt.totalMemory ());
System.out.println("java");
System.exit(0);
System.out.println("hungry4java.blogspot.com");
}
}



No comments:

Post a Comment