Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 47

Multithreaded Programming

• Java is a multi-threaded programming language which means


we can develop multi-threaded program using Java.
• A multi-threaded program contains two or more parts that can
run concurrently and each part can handle a different task at
the same time making optimal use of the available resources
specially when your computer has multiple CPUs.
• By definition, multitasking is when multiple processes share
common processing resources such as a CPU.
• Multi-threading extends the idea of multitasking into
applications where you can subdivide specific operations
within a single application into individual threads.
• Each of the threads can run in parallel.
• The OS divides processing time not only among different
applications, but also among each thread within an application.
• Multi-threading enables you to write in a way where multiple
activities can proceed concurrently in the same program.
Life Cycle of a Thread
Thread Priorities
• Every Java thread has a priority that helps the
operating system determine the order in which
threads are scheduled.
• Java thread priorities are in the range between
MIN_PRIORITY (a constant of 1) and
MAX_PRIORITY (a constant of 10). By default, every
thread is given priority NORM_PRIORITY (a
constant of 5).
• Threads with higher priority are more important to
a program and should be allocated processor time
before lower-priority threads.
• 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:
• A thread can voluntarily relinquish control. This is done
by explicitly yielding, sleeping, or blocking on pending
I/O. 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.
Synchronization
• For example, if you want two threads to communicate
and share a complicated data structure, such as a
linked list, you need some
• way to ensure that they don’t conflict with each other.
That is, you must prevent one thread from writing data
while another thread is in the middle of reading it.
• For this purpose, Java implements an elegant twist on
an age-old model of interprocess synchronization: the
monitor
• Once a thread enters a monitor, all other threads must
wait until that thread exits the monitor.
• In this way, a monitor can be used to protect a shared
asset from being manipulated by more than one thread
at a time.
The Thread Class and the Runnable Interface
• Java’s multithreading system is built upon the
Thread class, its methods, and its companion
interface, Runnable.
• To create a new thread, your program will either
extend Thread or implement the Runnable
interface.
The Thread class defines several
methods that help manage threads
The Main Thread
• When a Java program starts up, one thread begins
running immediately.
• This is usually called the main thread of your
program, because it is the one that is executed
when your program begins.
• The main thread is important for two reasons:
– It is the thread from which other “child” threads
will be spawned.
– Often, it must be the last thread to finish
execution because it performs various shutdown
actions.
• The main thread is created automatically when your program is started,
it can be controlled through a Thread object. To do so, you must obtain
a reference to it by calling the method currentThread( ).
• class CurrentThreadDemo {
• public static void main(String args[]) {
• Thread t = Thread.currentThread();
• System.out.println("Current thread: " + t);
• // change the name of the thread
• t.setName("My Thread");
• System.out.println("After name change: " + t);
• try {
• for(int n = 5; n > 0; n--) {
• System.out.println(n);
• Thread.sleep(1000);
• }
• } catch (Interrupted Exception e) {
• System.out.println("Main thread interrupted");
• }}}
Output
• Current thread: Thread[main,5,main]
• After name change: Thread[MyThread,5,main]
• 5
• 4
• 3
• 2
• 1
Creating a Thread
• In the most general sense, you create a thread by
instantiating an object of type Thread.
• Java defines two ways in which this can be
accomplished:
– You can implement the Runnable interface.
– You can extend the Thread class, itself.
1) Implementing Runnable
• The easiest way to create a thread is to create a
class that implements the Runnable interface.
• To implement Runnable, a class need only
implement a single method called run( ), which is
declared like this:
• public void run( )
• run( ) can call other methods, use other classes,
and declare variables, just like the main thread can.
• The only difference is that run( ) establishes the
entry point for another, concurrent thread of
execution within your program.
• This thread will end when run( ) returns.
• After you create a class that implements Runnable,
you will instantiate an object of type Thread from
within that class.
• Thread defines several constructors. The one that
we will use is shown here:
• Thread(Runnable threadOb, String threadName)
• In this constructor, threadOb is an instance of a class
that implements the Runnable interface.
• This defines where execution of the thread will begin.
The name of the new thread is specified by
threadName.
• After the new thread is created, it will not start
running until you call its start( ) method, which is
declared within Thread.
• In essence, start( ) executes a call to run( ).
Simple example
• class Mythread implements Runnable
• {
• public void run()
• {
• System.out.println(“Hello”);
• }
• }
• class Thread{
• public static void main(String args[])
• {
• Mythread x= new Mythread();
• Thread t=new Thread(x);
• t.start();
• }
• }
Here is an example that creates a new thread and starts it
running:
• class NewThread implements Runnable {
• Thread t;
• NewThread() {
• // Create a new, second thread
• t = new Thread(this, "Demo Thread");
• System.out.println("Child thread: " + t);
• t.start(); // Start the thread
• }
• // This is the entry point for the second thread.
• public void run() {
• try {
• for(int i = 5; i > 0; i--) {
• System.out.println("Child Thread: " + i);
• Thread.sleep(500);
• }
• } catch (InterruptedException e) {
• System.out.println("Child interrupted.");
• }
• System.out.println("Exiting child thread.");
• }}
• class ThreadDemo {
• public static void main(String args[]) {
• new NewThread(); // create a new thread
• try {
• for(int i = 5; i > 0; i--) {
• System.out.println("Main Thread: " + i);
• Thread.sleep(1000);
• }
• } catch (InterruptedException e) {
• System.out.println("Main thread interrupted.");
• }
• System.out.println("Main thread exiting.");
• }
• }
• Child thread: Thread[Demo Thread,5,main]
• Main Thread: 5
• Child Thread: 5
• Child Thread: 4
• Main Thread: 4
• Child Thread: 3
• Child Thread: 2
• Main Thread: 3
• Child Thread: 1
• Exiting child thread.
• Main Thread: 2
• Main Thread: 1
• Main thread exiting.
Extending Thread
• The second way to create a thread is to create a
new class that extends Thread, and then to create
an instance of that class.
• The extending class must override the run( )
method, which is the entry point for the new
thread. It must also call start( ) to begin execution
of the new thread.
• public class FirstThread extends Thread
• {
•     public void run()
•   {
•         for (int i=1; i<=10; i++)
•      {
•                System.out.println( "Messag from First Thread : " +i);
•       
•         try
•         {
•            Thread.sleep(1000);
•         }
•         catch (InterruptedException  interruptedException)
•         {
•                    System.out.println(  "First Thread is interrupted when it is 
sleeping" +interruptedException);
•         }
•       }
•    }
• }
• public class SecondThread extends Thread
• {
•  
•   public void run()
•   {
•  
•     for (int i=1; i<=10; i++)
•     {
•        System.out.println( "Messag from Second Thread : " +i);
•             try
•        {
•           Thread.sleep (1000);
•        }
•        catch (InterruptedException interruptedException)
•        {
•                   System.out.println( "Second Thread is interrupted when it is sleeping"
+interruptedException);
•        }
•     }
•   }
• }
• public class ThreadDemo
• {
•  
•   public static void main(String args[])
•   {
•  
•     //Creating an object of the first thread
•     FirstThread   firstThread = new FirstThread();
•  
•     //Creating an object of the Second thread
•     SecondThread   secondThread = new SecondThread();
•  
•     //Starting the first thread
•     firstThread.start();
•  
•     //Starting the second thread
•     secondThread.start();
•   }
• }
• Output of ThreadDemo
Using isAlive() and join()
• Sometimes one thread needs to know when
another thread is ending.
• In java, isAlive() and join() are two different
methods to check whether a thread has finished
its execution.
• 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
• 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
Example isAlive()
• public class MyThread extends Thread {
• public void run()
• { 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();
• System.out.println(t1.isAlive());
System.out.println(t2.isAlive());
• }}
Example join()
• class TestJoinMethod1 e •  TestJoinMethod1 t3=ne
xtends Thread{   w TestJoinMethod1();  
•  public void run(){   •  t1.start();  
•   for(int i=1;i<=5;i++){   •  try{  
•    try{   •   t1.join();  
•     Thread.sleep(500);   •  }catch(Exception e)
•    }catch(Exception e) {System.out.println(e);}  
{System.out.println(e);}   •   
•   System.out.println(i);   •  t2.start();  
•   }   •  t3.start();  
•  }   •  }  
• public static void main(St • }  
ring args[]){  
•  TestJoinMethod1 t1=ne
w TestJoinMethod1();  
•  TestJoinMethod1 t2=ne
Output
• 1
• 2
• 3
• 4
• 5
• 1
• 1
• 2
• 2
• 3
• 3
• 4
• 4
• 5
• 5
Threads priority
• To set a thread’s priority, use the setPriority( ) method, which is
a member of Thread.
• This is its general form:
• final void setPriority(int level)
• Here, level specifies the new priority setting for the calling thread.
The value of level must be within the range MIN_PRIORITY and
MAX_PRIORITY. Currently, these values are 1 and 10,
respectively.
• To return a thread to default priority, specify NORM_PRIORITY,
which is currently 5. These priorities are defined as static final
variables within Thread.
• You can obtain the current priority setting by calling the
getPriority( ) method of Thread, shown here:
• final int getPriority( )
• class TestMultiPriority1 extends Thread
• {   public void run(
• )
{     System.out.println("running thread name is:"+Thre
ad.currentThread().getName()); 
•     System.out.println("running thread priority is:"+Thr
ead.currentThread().getPriority());
•       } 
•   public static void main(String args[])
• {    TestMultiPriority1 m1=new TestMultiPriority1);    T
estMultiPriority1 m2=new TestMultiPriority1();    m1.s
etPriority(Thread.MIN_PRIORITY); 
   m2.setPriority(Thread.MAX_PRIORITY);   
 m1.start();    m2.start();   
   }  }
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.
• Key to synchronization is the concept of the monitor (also called
a semaphore)
• . A monitor is an object that is used as a mutually exclusive lock,
or mutex.
• 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.
Understanding the problem without
Synchronization
• 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;  }  
• 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();
•   }  } 
• Output:
• 5
• 100
• 10
• 200
• 15
• 300
• 20
• 400
• 25
• 500
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.
• 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  MyThread
1 t1=new MyThread1(obj); 
•  MyThread2 t2=new MyThread2(obj);
•   t1.start();
•   t2.start();  
• }  }  
• Output:
• 5
• 10
• 15
• 20
• 25
• 100
• 200
• 300
• 400
• 500
Inter-thread communication
• Inter-thread communication or Co-operation is all
about allowing synchronized threads to communicate
with each other.
• It is implemented by following methods of Object class:
• wait()
• notify()
• notifyAll()
• 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.
• class Customer
• {  int amount=10000;
•     synchronized void withdraw(int amount)
• {  System.out.println("going to withdraw...");
•     if(this.amount<amount)
• {  System.out.println("Less balance; waiting for deposit..."); 
•  try{wait();}
• catch(Exception e){}
•   } 
•  this.amount-=amount;  
• System.out.println("withdraw completed...");  }
• synchronized void deposit(int amount)
• {  System.out.println("going to deposit...");
•   this.amount+=amount; 
•  System.out.println("deposit completed... ");  
• notify();  }  } 
• class Test{  
• public static void main(String args[]){  
• final Customer c=new Customer();  
• new Thread(){  
• public void run(){c.withdraw(15000);}  
• }.start();  
• new Thread(){  
• public void run(){c.deposit(10000);}  
• }.start();  
•   
• }}  
• Output:
• going to withdraw...
• Less balance; waiting for deposit...
• going to deposit...
• deposit completed...
• withdraw completed
Deadlock
• Deadlock in java is a part of multithreading. 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.
• public class TestDeadlockExample1
•  {    public static void main(String[] args) 
• {      final String resource1 = "ratan jaiswal";  
•     final String resource2 = "vimal jaiswal";
•       // t1 tries to lock resource1 then resource2 
•   Thread t1 = new Thread();
•  {        public void run()
•  {            synchronized (resource1)
•  {             System.out.println("Thread 1: locked resource 1");               t
ry { Thread.sleep(100);} 
• catch (Exception e) {}          
•      synchronized (resource2)
•  {              System.out.println("Thread 1: locked resource 2");             } 
          }        }      };  
•  // t2 tries to lock resource2 then resource1
•       Thread t2 = new Thread()
•  {        public void run()
•  {          synchronized (resource2)
 {  System.out.println("Thread 2: locked resource 2");              
try { Thread.sleep(100);
} catch (Exception e) {}       
       synchronized (resource1)
 {              System.out.println("Thread 2: locked resource 1");  
    
      }          }        }      };     
         t1.start();      t2.start();
    }  }  
Output: Thread 1: locked resource 1
Thread 2: locked resource 2
Stop()
• public class CounterThread implements Runnable {
•  
•     private int counter = 0;
•      
•     @Override
•     public void run() {
•         for (int i=0; i<10; i++) {
•             counter++;
•             System.out.println("Counter is :" + counter + " --- Current time is:" + new Date());
•             try {
•                 Thread.sleep(500);
•                 if (counter == 5) {
•                     Thread.currentThread().stop();
•                 }
•             } catch (InterruptedException e) {
•                 e.printStackTrace();
•             }
•         }
•     }
•  
•     public int getCounter() {
•         return counter;
•     }
• }
• package com.reallybigindex.java.threads;
•  
• public class CounterDemo {
•  
•     public static void main(String[] args) {
•          
•         CounterThread counter = new CounterThread();
•         Thread t1 = new Thread(counter);
•         t1.start();
•  
•         for (int i = 0; i<10; i++) {
•             try {
•                 System.out.println("Main thread: " + i);
•                 Thread.sleep(1000);
•                 if (i == 5) {
•                     t1.resume();
•                 }
•             } catch (Exception e) {
•                 e.printStackTrace();
•             }
•         }
•     }
• }

Suspend() and resume()
package com.reallybigindex.java.threads;
•  
• import java.util.Date;
•  
• public class CounterThread implements Runnable {
•  
•     private int counter = 0;
•      
•    
•     public void run() {
•         for (int i=0; i<10; i++) {
•             counter++;
•             System.out.println("Counter is :" + counter + " --- Current time is:" + new Date());
•             try {
•                 Thread.sleep(500);
•                 if (counter == 5) {
•                     Thread.currentThread().suspend();
•                 }
•             } catch (InterruptedException e) {
•                 e.printStackTrace();
•             }
•         }
•     }
•  
•     public int getCounter() {
•         return counter;
•     }
• }

You might also like