Multi Threading - Ways to Define a Thread Part-1

Thread Definition

A thread is a flow of execution where each thread involves in a separate independent task. If there is any dependencies between two tasks then we shouldn't use multi threading there.

How to define a thread: 
In java we can define a thread in the following ways - 
  1. By Extending java.lang.Threads class
  2. By Implementing java.lang.Runnable class
Define a thread by Extending java.lang.Threads class:
Here is an example of defining a thread by extending Threads class - 

public class MyThread extends Thread{
@Override
//Code block inside run() method executes under the child/sub thread MyThread
public void run() {
for(int i=0; i<10; i++){
System.out.println("Sub/Child Thread");
}
}
}

To create a new thread extending Thread class, we need to override the run() method always.
  • Definition of Thread : The above "MyThread" class is called thread definition.
  • Job of Thread: The code blocks inside the "run()" method is called the job of thread.
The following class is an usage example of our newly created Thread:


public class MyThreadMain {

public static void main (String [] args){
//Thread Initialization
DemoExtendingThread myThreadDemo = new DemoExtendingThread();
//Starting our Thread
myThreadDemo.start();
  for(int i=0; i<10; i++){
System.out.println("Main/Default Thread");
}
}
}

Main Thread: Every program written in java creates a thread by default is called the Main Thread. Even if you haven't define any thread in java then the main thread is always created by default.

Child Thread: When we create a new thread in our program (as like the above example "MyThread"), is a sub/child Thread of our programs Main Thread (default Thread).

In the above "Thread usage example" the code blocks inside run() method of MyThread class executes under child thread. And the for loop blocks inside the main method of MyThreadMain class executes under the programs main thread. 

Basically Main Thread call main method of the program and executes all other code blocks of the program except the codes inside a particular threads run() method.


Thread Scheduler:
It's the part of JVM that defines which thread will be executed next. If multiple threads are waiting to get executed, then which threads will be executed first is decided by the Thread Scheduler. But we don't know about which algorithm the Thread Scheduler will use to execute the threads (such as FIFO, LIFO, Round Robin etc), it varies from JVM to JVM.

So when it's time to implement multi threading, then there is no guarantee for exact output. But we can provide several possible outputs. 

Here is some sample outputs after executing the above program:



Now we can see the order of execution is unpredictable and hence the output.

Difference between invoking run() VS start() method:
In the above main class "MyThreadMain.java" we have invoked start() method instead of run() method from "MyThread.java" class. Here start() is a method of super class "Thread.java" and we haven't overriden it as like the run() method. So what would have happened if we did that?

If we would call the run() method directly from the MyThreadMain.java class then the run() method would have executed without creating a new flow of execution or thread (that means as like a typical java method). Then the run() would have executed under the main/default thread of our program.

So by invoking the super class start() method, we actually create a sub flow of execution and implement concurrency indeed.

Role of start() method:

  1. Register our thread with Thread Scheduler
  2. Perform all other associated activities 
  3. Invoke the run() method
  4. start() invokes the no-argument run() method only. So, overloading should be done explicitly.
  5. In java we must invoke start() method to create a new flow/thread of execution
Overriding start()method:
We should never override the start() method but the following is allowed:


public class MyThread extends Thread{
//Block of code executes under main/default program thread
@Override
public synchronized void start() {
super.start();
System.out.println("Start Method");
}
//Block of code executes under sub/child thread
@Override
public void run() {
for(int i=0; i<5; i++){
System.out.println("Sub/Child Thread");
}
}
}


In the block of code above, if we don't put "super.start()" inside the start() method then no thread will be created. The start() will work like a typical java method and will execute under the main/default thread of the program.

Thread Life-cycle:

We should not start a thread again after it's execution. Otherwise it'll throw IllegalThreadStateException 

Comments