Unit III: Multithreading – Java Programming - BCA Notes (Pokhara University)

Breaking

Friday, July 24, 2020

Unit III: Multithreading – Java Programming

Introduction to Thread and Process in Java Programming:

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

Thread:

Thread is an execution unit that is part of a process. A process can have multiple threads, all executing at the same time. It is a unit of execution in concurrent programming. A thread is lightweight and can be managed independently by a scheduler. It helps you to improve the application performance using parallelism.

Multiple threads share information like data, code, files, etc. We can implement threads in three different ways:

  1. Kernel-level threads
  2. User-level threads
  3. Hybrid threads

Here Are Important Properties Of Thread:

  1. Single system call can create more than one thread.
  2. Threads share data and information.
  3. Threads shares instruction, global, and heap regions. However, it has its register and stack.
  4. Thread management consumes very few, or no system calls because of communication between threads that can be achieved using shared memory.

Process:

A process is the execution of a program that allows us to perform the appropriate actions specified in a program. It can be defined as an execution unit where a program runs. The OS helps us to create, schedule and terminates the processes which are used by CPU. The other processes created by the main process are called the child process.

Process operations can be easily controlled with the help of PCB (Process Control Block). We can consider it as the brain of the process, which contains all the crucial information related to processing like process id, priority, state, and contents CPU register, etc.

Here Are The Important Properties Of The Process:

  1. The creation of each process requires separate system calls for each process.
  2. It is an isolated execution entity and does not share data and information.
  3. Processes use the IPC (Inter-Process Communication) mechanism for communication that significantly increases the number of system calls.
  4. Process management takes more system calls.
  5. A process has its stack, heap memory with memory, and data map.

Difference between Thread and Process:

PROCESS

THREAD

Process means any program is in execution.

Thread means a segment of a process.

The process takes more time to terminate.

The thread takes less time to terminate.

It takes more time for creation.

It takes less time for creation.

It also takes more time for context switching.

It takes less time for context switching.

The process is less efficient in terms of communication.

Thread is more efficient in terms of communication.

Process consume more resources.

Thread consume fewer resources.

The process is isolated.

Threads share memory.

The process is called a heavyweight process.

Thread is called a lightweight process.

Process switching uses interface in the operating system.

Thread switching does not require to call an operating system and cause an interrupt to the kernel.

If one server process is blocked no other server process can execute until the first process unblocked.

The second thread in the same task could run, while one server thread is blocked.

The process has its own Process Control Block, Stack, and Address Space.

Thread has Parents’ PCB, its own Thread Control Block, and Stack and common Address space.

Multithreading Concepts in Java Programming:

Multithreading in java is a process of executing multiple threads simultaneously. Thread is basically a lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading, both are used to achieve multitasking.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

But we use multithreading than multiprocessing because threads share a common memory area. They don't allocate separate memory areas so saves memory, and context-switching between the threads takes less time than process. Java Multithreading is mostly used in games, animation, etc.

Advantages of Java Multithreading:

  1. It doesn't block the user because threads are independent and you can perform multiple operations at the same time.
  2. We can perform many operations together so it saves time.
  3. Threads are independent so it doesn't affect other threads if an exception occurs in a single thread.

Definition of Multitasking:

Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking can be achieved in two ways:

1. Process-based Multitasking (Multiprocessing):

  1. Each process have its own address in memory i.e. each process allocates separate memory area.
  2. The process is heavyweight.
  3. Cost of communication between the processes is high.
  4. Switching from one process to another requires some time for saving and loading registers, memory maps, updating lists, etc.

2. Thread-based Multitasking (Multithreading):

  1. Threads share the same address space.
  2. Thread is lightweight.
  3. Cost of communication between the thread is low.

Thread Life Cycle In Java Programming:

A thread goes through the various stages of the life cycle. It has stages such as a new stage or born stage, runnable, waiting stage, and dead stage. The life cycle of the thread in java is controlled by JVM. The java thread states are as follows:

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

1. New:

It is a stage where a new thread begins its life cycle. It remains in this state until the program starts the thread. The thread is in a new state if we create an instance of Thread class but before the invocation of start() method. It is also referred to as a born thread.

2. Runnable:

It is the second state of the thread life cycle, the thread becomes runnable after the invocation of start() method, but the thread scheduler has not selected it to be the running thread. A thread in this state is considered to be executing its task. In simpler terms, a thread actually executes in this state.

3. Waiting:

There maybe a condition where sometimes a thread in transitions may have to wait while the thread executes another thread, so this state is known as waiting state. A thread transition may come back to the runnable state only when another thread signals the waiting thread to continue executing.

4. Timed Waiting:

A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.

5. Terminated:

A runnable thread enters the terminated state when it completes its task or otherwise terminates. It is also known as a dead state. 

How to Create Thread in Java Programming:

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

There are two ways to create a thread:

1. Create a Thread by Implementing a Runnable Interface:

If our class is intended to be executed as a thread then we can achieve this by implementing a Runnable interface. We need to follow three basic steps:

Step 1:

In the first step, we need to implement a run() method provided by a Runnable interface. This method provides an entry point for the thread and we put our complete business logic inside this method. Following is a simple syntax of the run() method:

public void run( )

Step 2:

In the second step, we will instantiate a Thread object using the following constructor:

Thread(Runnable threadObj, String threadName);

Where, threadObj is an instance of a class that implements the Runnable interface and threadName is the name given to the new thread.

Step 3:

In the third step, Once a Thread object is created, we can start it by calling start() method, which executes a call to run( ) method. Following is a simple syntax of start() method:

void start();

Example:

class RunnableDemo implements Runnable {

   private Thread t;

   private String threadName;

  

   RunnableDemo( String name) {

      threadName = name;

      System.out.println("Creating " +  threadName );

   }

   public void run() {

      System.out.println("Running " +  threadName );

      try {

         for(int i = 4; i > 0; i--) {

            System.out.println("Thread: " + threadName + ", " + i);

            // Let the thread sleep for a while.

            Thread.sleep(50);

         }

      }catch (InterruptedException e) {

         System.out.println("Thread " +  threadName + " interrupted.");

      }

      System.out.println("Thread " +  threadName + " exiting.");

   }

   public void start () {

      System.out.println("Starting " +  threadName );

      if (t == null) {

         t = new Thread (this, threadName);

         t.start ();

      }

   }

}

public class TestThread {

   public static void main(String args[]) {

      RunnableDemo R1 = new RunnableDemo( "Thread-1");

      R1.start();

      RunnableDemo R2 = new RunnableDemo( "Thread-2");

      R2.start();

   }  

}


2. Create a Thread by Extending a Thread Class:

The second way to create a thread is to create a new class that extends Thread class using the following two simple steps. This approach provides more flexibility in handling multiple threads created using available methods in Thread class.

Step 1:

We need to override run( ) method available in Thread class. This method provides an entry point for the thread and we put our complete business logic inside this method. Following is a simple syntax of run() method:

public void run( )

Step 2:

Once Thread object is created, we can start it by calling start() method, which executes a call to run() method. Following is a simple syntax of start() method:

void start( );

Example:

class ThreadDemo extends Thread {

   private Thread t;

   private String threadName;

   ThreadDemo( String name) {

      threadName = name;

      System.out.println("Creating " +  threadName );

   }

   public void run() {

      System.out.println("Running " +  threadName );

      try {

         for(int i = 4; i > 0; i--) {

            System.out.println("Thread: " + threadName + ", " + i);

            // Let the thread sleep for a while.

            Thread.sleep(50);

         }

      }catch (InterruptedException e) {

         System.out.println("Thread " +  threadName + " interrupted.");

      }

      System.out.println("Thread " +  threadName + " exiting.");

   }

   public void start () {

      System.out.println("Starting " +  threadName );

      if (t == null) {

         t = new Thread (this, threadName);

         t.start ();

      }

   }

}

public class TestThread {

   public static void main(String args[]) {

      ThreadDemo T1 = new ThreadDemo( "Thread-1");

      T1.start();

      ThreadDemo T2 = new ThreadDemo( "Thread-2");

      T2.start();

   }  

}


Thread Methods in Java Programming:

Following is the list of important methods available in the Thread class.

  • public void run(): is used to perform an action for a thread.
  • public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
  • public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.
  • public void join(): waits for a thread to die.
  • public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
  • public int getPriority(): returns the priority of the thread.
  • public int setPriority(int priority): changes the priority of the thread.
  • public String getName(): returns the name of the thread.
  • public void setName(String name): changes the name of the thread.
  • public Thread currentThread(): returns the reference of currently executing thread.
  • public int getId(): returns the id of the thread.
  • public Thread.State getState(): returns the state of the thread.
  • public boolean isAlive(): tests if the thread is alive.
  • public void yield(): causes the currently executing thread object to temporarily pause and allow other threads to execute.
  • public void suspend(): is used to suspend the thread(deprecated).
  • public void resume(): is used to resume the suspended thread(deprecated).
  • public void stop(): is used to stop the thread(deprecated).
  • public boolean isDaemon(): tests if the thread is a daemon thread.
  • public void setDaemon(boolean b): marks the thread as daemon or user thread.
  • public void interrupt(): interrupts the thread.
  • public boolean isInterrupted(): tests if the thread has been interrupted.
  • public static boolean interrupted(): tests if the current thread has been interrupted.
  • public static boolean holdsLock(Object x): Returns true if the current thread holds the lock on the given Object.
  • public static void dumpStack(): Prints the stack trace for the currently running thread, which is useful when debugging a multithreaded application.

Priority of a Thread (Thread Priority) in Java Programming:

Each thread has a priority. Priorities are represented by a number between 1 and 10. In most cases, the 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. Threads with higher priority are more important to a program and should be allocated processor time before lower-priority threads.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

3 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 TestMultiPriority 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[]){ 

  TestMultiPriority m1=new TestMultiPriority(); 

  TestMultiPriority m2=new TestMultiPriority(); 

  m1.setPriority(Thread.MIN_PRIORITY); 

  m2.setPriority(Thread.MAX_PRIORITY); 

  m1.start(); 

  m2.start(); 

 } 

}


Thread Synchronization in Java Programming:

When we start two or more threads within a program, there may be a situation when multiple threads try to access the same resource and finally they can produce unforeseen results due to concurrency issues. For example, if multiple threads try to write within the same file then they may corrupt the data because one of the threads can override data or while one thread is opening the same file at the same time another thread might be closing the same file.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

So there is a need to synchronize the action of multiple threads and make sure that only one thread can access the resource at a given point in time. Java programming language provides a very handy way of creating threads and synchronizing their task.

Example:

import java.util.Scanner;

class Account{

      private int balance;

      public Account(int bal){

            this.balance = bal;

      }

      public boolean isSufficentBalance(int amount){

            if(balance > amount){

                  return(true);

            }

            else{

                  return(false);

            }

      }

      public void withdraw(int wd){

            balance = balance - wd;

            System.out.println("Withdrawl Amount = " + wd);

            System.out.println("Current Balance = " + balance);

      }

}

 

class Customer implements Runnable{

      private final Account account;

        private String name;

      public Customer(Account account, String n){

            this.account = account;

                name = n;

      }

        @Override

      public void run(){

            Scanner scan = new Scanner(System.in);

            synchronized(account){

                  System.out.println(name + ",Enter amount: ");

                  int amount = scan.nextInt();

                  if(account.isSufficentBalance(amount)){

                               System.out.println(name);

                        account.withdraw(amount);

                  }

                  else{

                        System.out.println("Insufficent Balance");

                  }

            }

      }

}

public class ThreadExample{

    public static void main(String [] args){

      Account a1 = new Account(1000);

      Customer c1 = new Customer(a1,"Ramesh");

      Customer c2 = new Customer(a1,"Samir");

      Thread t1 = new Thread(c1);

      Thread t2 = new Thread(c2);

      t1.start();

      t2.start();

    }

}


Synchronized Method in Java Programming:

If we declare any method as synchronized, it is known as the synchronized method. A 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.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

Example:

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; 

public void run(){ 

t.printTable(5); 

 

class MyThread2 extends Thread{ 

Table t; 

MyThread2(Table t){ 

this.t=t; 

public void run(){ 

t.printTable(100); 

 

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(); 

}


Synchronized Block in Java Programming:

Synchronized block can be used to perform synchronization on any specific resource of the method.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

Suppose we have 50 lines of code in our method, but we want to synchronize only 5 lines, then we can use a synchronized block. If we put all the codes of the method in the synchronized block, it will work same as the synchronized method.

Points To Remember For Synchronized Block:

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

Syntax:

synchronized (object reference expression) {  

  //code block  

Example:

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);} 

     } 

   } 

 }//end of the method 

class MyThread1 extends Thread{ 

Table t; 

MyThread1(Table t){ 

this.t=t; 

public void run(){ 

t.printTable(5); 

}

class MyThread2 extends Thread{ 

Table t; 

MyThread2(Table t){ 

this.t=t; 

public void run(){ 

t.printTable(100); 

public class TestSynchronizedBlock1{ 

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(); 

}


Static Synchronization in Java Programming:

If we make any static method as synchronized, the lock will be on the class not on object.

Multithreading in Java Programming, Introduction to Thread and Process in Java Programming, Multithreading concepts, Thread Life cycle, How to Create Thread in Java Programming, Thread priorities, Thread Synchronization in Java Programming, Thread Methods in Java Programming

Problem without Static Synchronization:

Suppose there are two objects of a shared class (e.g. Table) named object1 and objects. In the case of synchronized method and synchronized block, there cannot be interference between t1 and t2 or t3 and t4 because t1 and t2 both refer to a common object that has a single lock. But there can be interference between t1 and t3 or t2 and t4 because t1 acquires another lock and t3 acquires another lock. I want no interference between t1 and t3 or t2 and t4.Static synchronization solves this problem.

Example:

In this example we are applying synchronized keyword on the static method to perform static synchronization.

class Table{ 

 synchronized static void printTable(int n){ 

   for(int i=1;i<=10;i++){ 

     System.out.println(n*i); 

     try{ 

       Thread.sleep(400); 

     }catch(Exception e){} 

   } 

 } 

class MyThread1 extends Thread{ 

public void run(){ 

Table.printTable(1); 

class MyThread2 extends Thread{ 

public void run(){ 

Table.printTable(10); 

class MyThread3 extends Thread{ 

public void run(){ 

Table.printTable(100); 

class MyThread4 extends Thread{ 

public void run(){ 

Table.printTable(1000); 

public class TestSynchronization4{ 

public static void main(String t[]){ 

MyThread1 t1=new MyThread1(); 

MyThread2 t2=new MyThread2(); 

MyThread3 t3=new MyThread3(); 

MyThread4 t4=new MyThread4(); 

t1.start(); 

t2.start(); 

t3.start(); 

t4.start(); 

}

No comments:

Post a Comment

If you have any doubt, then don't hesitate to drop comments.