Java Threading - Multithreading

Advertisements

Multitasking

Multitasking means running more than one process simultaneously is called Multitasking. There are two types of multitasking:

  • Process based
  • Thread based

Process based multitasking : Running more than one processes simultaneously and each process is an independent process of different application is called process based multitasking. Example, It allows us to listen music using mp3 player while creating PowerPoint presentation using MS PowerPoint. Both Mp3 player and MS PowerPoint are independent applications.

Thread based multitasking : Running more than one processes simultaneously and each process is an independent process of same application is called thread based multitasking. Example, While writing MS word document, MS word can check the spelling and grammatical errors, at the same time it can also auto-correct these spelling and grammatical errors. Both, error checking and auto-correct are independent processes and comes under the same application.

Java Multithreading

Thread is an independent process of a single application. In Java, main() method is called the "main thread" of our application and other program level threads are called child thread. We can develop multithreading application in two ways.

  • Extends Thread Class
  • Implements Runnable Interface

Java MultiThreading Using Extends Thread Class

Steps for creating thread using Thread class

STEP 1:

Create a common class for all the threads.

STEP 2:

Create derived classes of Thread class.

STEP 3:

Override run() method of Thread class into derived class. The run() method is used to define the new thread.

STEP 4:

Create an object of common class which is created at step 1.

STEP 5:

Create objects of derived classes of Thread class and pass the object of common class to all the derived class constructors.

STEP 6:

Invoke start() method with derived class objects to execute the thread. We can't invoke run() method directly. If we invoke run() method directly, run() method will execute as a normal method not as a thread. The start() method tells JVM to consider run() method as new thread and then JVM will invoke run() method as a new separate thread.

Example of multithreading using Thread class


//ThreadDemo.java

    class Pattern
    {
        public void DisplayA()
        {
            for(int i=1;i<=25;i++)
            System.out.print("A");
        }

        public void DisplayB()
        {
            for(int i=1;i<=25;i++)
            System.out.print("B");
        }

        public void DisplayC()
        {
            for(int i=1;i<=25;i++)
            System.out.print("C");
        }
    }

    class ThreadA extends Thread
    {
        Pattern P;

        ThreadA(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayA();
        }
    }

    class ThreadB extends Thread
    {
        Pattern P;

        ThreadB(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayB();
        }
    }

    class ThreadC extends Thread
    {
        Pattern P;

        ThreadC(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayC();
        }
    }

    class ThreadDemo
    {
        public static void main(String arg[])
        {

            Pattern P = new Pattern();

            ThreadA t1 = new ThreadA(P);    //Statement 1
            ThreadB t2 = new ThreadB(P);    //Statement 2
            ThreadC t3 = new ThreadC(P);    //Statement 3

            t1.start();
            t2.start();
            t3.start();

        }
    }

In the above example, we have defined a common class Pattern and pass the object P of Pattern class to the derived classes such as ThreadA, ThreadB , ThreadC as shown in statement 1, 2 and 3.

ThreadA will invoke DisplayA() method of Pattern class.

ThreadB will invoke DisplayB() method of Pattern class.

ThreadC will invoke DisplayC() method of Pattern class.

We have compiled and run the above program three times and get three different results.


    Output 1:
    AAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBCCCCCCCCCCCCCC
    CCCBBBBBBBBBBBBBBCCCCCCCC

    Output 2:
    AABBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAA
    CCCCCCCCCCCCCCCCCCCCCCCCC

    Output 3:
    AAAAAAAABACABAACABAACABACCCCCCCCCCCCCCCCCCCCCCAAAA
    ABAAABBBBBBBBBBBBBBBBBBBB

As we can see, we have three different outputs of same example, this is b'coz all three threads are running simultaneously, but it doesn't mean that all threads are running at the same time. Thread Scheduler(part of JVM) handles the context switching of threads in such a way that it appears that they are running simultaneously.

Thread context switching means to switch from one thread to another thread.

Java MultiThreading Using Runnable Interface

It is always better to create a thread by implementing runnable interface b'coz if we create a thread using Thread class we can't inherit any other class but if we create a thread using runnable interface, we have always a chance to inherit a class in future.

Steps for creating thread using Runnable interface

STEP 1:

Create a common class for all the threads.

STEP 2:

Create derived classes of Runnable interface.

STEP 3:

Override run() method of Runnable interface into derived class. The run() method is used to define the new thread.

STEP 4:

Create an object of common class which is created at step 1.

STEP 5:

Create objects of derived classes of Runnable interface and pass the object of common class to all the derived class constructors.

STEP 6:

Create objects of Thread class and pass the object of derived class to each Thread class.

STEP 7:

Invoke start() method with Thread class objects to execute the thread. The start() method tells JVM to consider run() method as new thread and then JVM will invoke run() method as a new separate thread.

Example of multithreading using runnable interface


//RunnableInterfaceDemo.java

    class Pattern
    {

        public void DisplayA()
        {
            for(int i=1;i<=25;i++)
            System.out.print("A");
        }

        public void DisplayB()
        {
            for(int i=1;i<=25;i++)
            System.out.print("B");
        }

        public void DisplayC()
        {
            for(int i=1;i<=25;i++)
            System.out.print("C");
        }

    }

    class ThreadA implements Runnable
    {
            Pattern P;

        ThreadA(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayA();
        }
    }

    class ThreadB implements Runnable
    {

        Pattern P;

        ThreadB(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayB();
        }
    }

    class ThreadC implements Runnable
    {

            Pattern P;

        ThreadC(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayC();
        }
    }

    class RunnableInterfaceDemo
    {
        public static void main(String arg[])
        {

            Pattern P = new Pattern();

            ThreadA A = new ThreadA(P);
            ThreadB B = new ThreadB(P);
            ThreadC C = new ThreadC(P);


            Thread t1 = new Thread(A);
            Thread t2 = new Thread(B);
            Thread t3 = new Thread(C);

            t1.start();
            t2.start();
            t3.start();

        }
    }

    Output 1:
    AAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAA
    CCCCCCCCCCCCCCCCCCCCCCCCC

    Output 2:
    ABBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCAAAAA
    AAAAAAAAAAAAAABBBBAAAAABB

    Output 3:
    AAAAAAAABBBBBBBBBBBBBBBACABAACABAACABACCCCCCCCCCCC
    CCCCCCCCCCAAAAABAAABBBBBB

There is also three different outputs due to thread context switching as explained above.

Advertisement