Java Thread & Synchronization : How to use thread?


This is continuing article of previous post. In this article, we are going to see how to implement or use thread in java.

We can apply threading in two ways.
a. Extending Thread class : Which is self executable (can run directly)
b. Implement runnable interface : Which is not self executable , need to include a thread to execute this.
Basically they are operated by same technique, if you see Thread class which is implementing runnable interface. That we will override. Let’s see those two
A. Extending Thread class :
We need to first extend from thread class. I am creating MyThread class which extends Thread

public class MyThread extends Thread{
    public MyThread(){
        this("No Name Provided");
    }
    public MyThread(String name) {
        super.setName(name);
        System.out.println("Extended Thread Created: " + name+" : Status ->"+super.getState().toString());               
    }       
    public MyThread(Runnable arunnable, String name) {
        super(arunnable, name);
        System.out.println("Extended Thread Created with runnable : " + name+" : Status ->"+super.getState().toString());           
    }   
    @Override
    public void start(){// Changed start
        super.start();
        System.out.println("Thread started "+super.getName()+" : Status ->"+super.getState().toString());
    }
    @Override
    public void run() {// Changed run
        System.out.println("Thread is running "+super.getName()+" : Status ->"+super.getState().toString());       
    }   
}
In each initiation, I provide print so that we can understand how it is working. Now, lets see we make a method under main that calls my thread to run.
public static void runThreadByExtendingThread(){
        MyThread t;
        for(int i=0; i<=5; i++){
            t=new MyThread("T Name : "+i);   
            System.out.println("Thread Created, Serial = "+i+", Name :"+t.getName() +" ID : "+t.getId()+" Status : "+t.getState().toString());
            t.start();
            System.out.println("Thread started, Serial = "+i+", Name :"+t.getName() +" ID : "+t.getId()+" Status : "+t.getState().toString());
        }
    }

And  adding this to main

public static void main(String[] args) {
        try{
            runThreadByExtendingThread();
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }

If we run this , we can see following in console
image

So, from here, we can see, how status is changing for a particular thread. I pointed about initial created thread(0 th)
Benefits :
1. We can implement our own type of execution engine by overriding inherited method.
2. Full execution unit is in our control, so we can design full work flow type environment inside JVM in controlled way. This is very useful while designing your own framework or custom UI component or even custom test runner.

Weak points :
As we have to inherit, so, only our custom thread cant be inherit more.

B. Implement runnable interface :
This is so simple. We need to implement runnable and override run() method. This is our main execution engine. So, we make our own method runnable and then initiate with a thread, then the thread runs this. So, I am making my own Runnable class MyRunnable

public class MyRunnable implements Runnable{
    private static int counter=0;// to see how many time it is calling run()   
    public MyRunnable(){   
    }
    @Override
    public void run() {
        System.out.println("Runnable is running at -> runnable counter "+counter++);       
    }
}

And, like as previous method, make a method to call this.
public static void runThreadByImplementRunnable(){
        MyRunnable runnable;
        Thread t2;
        for(int i=0; i<=5; i++){
        runnable = new MyRunnable();
        t2=new Thread(runnable,"T Name : "+i);
        System.out.println("Thread Created, Serial = "+i+", Name :"+t2.getName() +" ID : "+t2.getId()+" Status : "+t2.getState().toString());
        t2.start();
        System.out.println("Name :"+t2.getName() +" ID : "+t2.getId()+" Status : "+t2.getState().toString());
    }
    }

And, calling this method from main 

public static void main(String[] args) {
        try{
            runThreadByImplementRunnable();
        }catch(Exception e)
        {
            e.printStackTrace();
        } 
}

If we run this we can see following in command line
image

From here, we can , initial thread (oth) created and running our run() method. we can see step by steps execution .
Thread 0, created –> become runnable and then start our run() method. And between that, another created. 

Note : Thread use start() to call run(), it is better not to call run() method by our self. Why? you can see in thread class, jvm make some steps before calling run to make it safe.

Benefits :
1. This is faster way to implement
2. No barrier on extending class, so, just implementing runnable is enough.

Weak points :
We cant have control on execution environment.

In here you can see source code form github. I will add more example under this multithreading source code.

In the next article, we are going to see, multi-threading & communication among them.

Please comment if you have any question.
Thanks.. :)

No comments:

Post a Comment