X

Play AlgoQuiz

Rate Us :



Share with Friends :

Menu

Multitasking :

Executing several tasks simultaneously is called multitasking. There are two types of multitasking :

  • process-based multitasking




  • thread-based multitasking




Process-based multitasking :

Executing several tasks simultaneously where each task is a separate independent process then it called process-based multitasking.

Example, while using our computer we can play music and at the same time we can browse internet and we can even download a file from internet. These all tasks are executing simultaneously and independent of each other. Hence, it is a process-based multitasking.

Process-based multitasking is best suited at "Operating System level".


Thread-based multitasking :

Executing several tasks simultaneously where each task is a separate independent part of the same problem is called thread-based multitasking and each independent part is called thread.

Thread-based multitasking is best suited at "Programmatic level".


Whether it is process-based or thread-based, the main objective of multitasking is to improve performance of the system by reducing response time.


Multithreading :

Multithreading is one of the distinct feature of Java programming. The aim of multithreading is to provide concurrent execution (if we perform multiple operations simultaneously then such type of execution is known as concurrent execution).

The main important application areas of multithreading are developing video games, multimedia graphics, implementing animations etc.

Java provides inbuilt support for multithreading by introducing a rich API (Thread, Runnable, ThreadGroup, ThreadLocal etc.). Being a programmer we have to know how to use these API and we are not responsible to define that API. Hence, development of multithreading programs is very easy in Java when compared to C++.


We can define a new thread in following two ways :


  • By extending Thread class




  • By implementing Runnable interface




Defining a thread by extending Thread class :


class Algo extends Thread
{
 public void run()
 {
   for(int i = 0 ; i <= 10 ; i++)
   {
     System.out.println("Child Thread");
   } //Job of thread
 }
}
class Example
{
 public static void main(String[ ] args)
  {
     Algo t = new Algo(); //instantiation of thread
     t.start(); //starting of a thread
     for(int i = 0 ; i <= 10 ; i++)
     {
       System.out.println("Main Thread");
     } //executing main thread
  }
}

Thread Scheduler :

Whenever multiple threads are waiting to get chance for execution then which thread will get chance first is decided by Thread Scheduler whose behaviour is JVM vendor dependent. Hence, we can't expect exact execution order and exact output. Thread Scheduler is the part of JVM. Due to the unpredictable behaviour of Thread Scheduler we can't expect exact output for the above program so we have the following various possible outcomes :

  • 10 times Main Thread followed by 10 times Child Thread

  • 10 times Child Thread followed by 10 times Main Thread

  • few times Main Thread followed by 10 times Child Thread then rest Main Thread

  • few times Child Thread followed by few times Main Thread then rest Child Thread and then rest Main Thread

By running the program multiple times we can obtain all provided pattern of result.


Difference between t.start() method and t.run() method :

In the case of t.start() method a new thread will be created and thread is responsible to execute run() method. But in case of t.run() method no new thread will be created and run() method will be executed just like a normal method call. In the above program if we are replacing t.start() method with t.run() method then the following exact output will come:

  • 10 times Child Thread followed by 10 times Main Thread

Importance of Thread class start() method :

To start a thread, the required mandatory activities (like registering the thread with Thread Scheduler etc.) will be performed automatically by Thread class start() method. Because of this facility programmer is not responsible to perform this activity and he is just responsible to define job of the thread. Hence, Thread class start() method plays very important role and without executing this method there is no chance of starting a new thread.


If we are not overriding run() method :

If we are not overriding run() method then Thread class run() method will be executed which has empty implementation and hence we can't get any output.

Example :

class Algo extends Thread { } class Example { public static void main(String[ ] args) throws Exception { Algo t = new Algo(); //instantiation of thread t.start(); //starting of a thread } } //save as : Example.java //compile as : javac Example.java //run as : java Example

Output :

nothing display

It is highly recommended to override run() method to define our job of thread.


Overloading of run() method :

Overloading of run() method is possible but Thread class start() method will always call no argument run() method but for other run() method we have to call explicitly just like a normal method call.

Example :

class Algo extends Thread { public void run() { System.out.println("run()"); } public void run(int a) { System.out.println("run(int a)"); } } class Example { public static void main(String[ ] args) throws Exception { Algo t = new Algo(); //instantiation of thread t.start(); //starting of a thread } } //save as : Example.java //compile as : javac Example.java //run as : java Example

Output :

run()

Overriding of start() method :

If we override start() method then start() method will be executed just like a normal method call and no new thread will be created.

Example :

class Algo extends Thread { public void start() { System.out.println("start()"); } public void run() { System.out.println("run()"); } } class Example { public static void main(String[ ] args) throws Exception { Algo t = new Algo(); //instantiation of thread t.start(); //starting of a thread } } //save as : Example.java //compile as : javac Example.java //run as : java Example

Output :

start()

Overriding of start() method and calling super method with super keyword :


Example :

class Algo extends Thread { public void start() { super.start(); System.out.println("start()"); } public void run() { System.out.println("run()"); } } class Example { public static void main(String[ ] args) throws Exception { Algo t = new Algo(); //instantiation of thread t.start(); //starting of a thread System.out.println("main()"); } }

There are three possible outcomes of the above program :-

start()
run()
main()


run() start() main()
start() main() run()

Life cycle of a thread :

Once we have created a thread object then it is said to be in new state or born state.

If we call start() method in the thread then it will be entered into ready or runnable state.

If Thread Scheduler allocates CPU space then the thread will be entered into running state.

If run() method completes it's execution then the thread will be entered into dead state.


After starting a thread we are not allowed to restart the same thread once again otherwise we will get runtime exception saying IllegalThreadStateException.

Within the run() method if we call super.start() then we will get the same runtime exception saying IllegalThreadStateException.

It is never recommended to override start() method but it is highly recommended to override run() method.


Defining a thread by implementing Runnable interface :

We can define a thread even by implementing Runnable interface. Runnable interface is present in java.lang package and contains only one method which is run() method.

class Algo implements Runnable
{
 public void run()
 {
   for(int i = 0 ; i <= 10 ; i++)
   {
     System.out.println("Child Thread");
   } //Job of thread
 }
}
class Example
{
 public static void main(String[ ] args)
  {
     Algo r = new Algo();
     Thread t = new Thread(r);
	 t.start(); //starting of a thread
     for(int i = 0 ; i <= 10 ; i++)
     {
       System.out.println("Main Thread");
     } //executing main thread
  }
}

We can't get exact output and the possible outcomes are :

  • 10 times Main Thread followed by 10 times Child Thread

  • 10 times Child Thread followed by 10 times Main Thread

  • few times Main Thread followed by 10 times Child Thread then rest Main Thread

  • few times Child Thread followed by few times Main Thread then rest Child Thread and then rest Main Thread

By running the program multiple times we can obtain all provided pattern of result.


Analysis :

MyRunnable r = new MyRunnable();
Thread t1 = new Thread();
Thread t2 = new Thread(r);

t1.start() :-

A new thread will be created which is responsible for execution of Thread class run() method.


t1.run() :-

No new thread will be created and Thread class run() will be executed just like a normal method call.


t2.start() :-

A new thread will be created which is responsible for execution of MyRunnable run() method.


t2.run() :-

No new thread will be created and MyRunnable run() method will be executed just like a normal method call.


r.start() :-

We will get compile time error saying start() method is not available in MyRunnable class.

Compile time error : cannot find symbol
                     symbol : method start()
                     location : class MyRunnable

r.run() :-

No new thread will be created and MyRunnable run() method will be executed just like a normal method call.


Best approach to define a thread :

Among the two ways of defining a thread, implements Runnable mechanism is recommended to use.

In the first approach our class always extends Thread class and hence there is no chance for extending any other class but in the second approach we can extend some other class also while implementing Runnable interface. Hence, it is recommended to use.


Constructors for Thread class :


Thread t = new Thread();
Thread t = new Thread(Runnable r);
Thread t = new Thread(String s);
Thread t = new Thread(Runnable r , String s);
Thread t = new Thread(ThreadGroup g , String s);
Thread t = new Thread(ThreadGroup g , Runnable r);
Thread t = new Thread(ThreadGroup g , Runnable r , String s);
Thread t = new Thread(ThreadGroup g , Runnable r , String s , long stacksize);

Getting and Setting name of the thread :

Every thread in Java has some name. It may be provided by the programmer or default name generated by JVM. We can get and set name of the thread by using the following methods of the Thread class.

public final String getName();
public final void setName(String s);

Example :

class Example { public static void main(String[ ] args) throws Exception { System.out.println(Thread.currentThread().getName()); Thread.currentThread().setName("algo"); System.out.println(Thread.currentThread().getName()); } } //save as : Example.java //compile as : javac Example.java //run as : java Example

Output :

main algo Note : We can get current executing thread reference by using following method of Thread class :- public static Thread currentThread();


X

MiniDoll :

MiniDoll is an application to learn with fun. You can play it to solve some tricky questions related to Java Programming. Either enjoy playing it alone or discuss with your friends to solve it. It is a simple approach to learn by solving questions. This application has different topics of Java and each topic is divided into three phases. Start solving from initial topic to final topic and by the end of every topic you can boost your concept of that topic.