www.000webhost.com
Threading in Java


Threading in Java

Core Java

An Instance of Thread is an object like any other object in Java, it contains variables and methods which lives and dies on the heap. But a Thread of Execution is an individual process which has its own stack call.
Even if you don’t create any thread in your program, thread will be running there and main() method will start that.


Type of Thread :-


Thread can be of two types :-

JVM exists an application only when all User Thread are complete.
JVM doesn’t care about the status of Daemon Thread.


How to Define Thread in java :-

Thread can be defined in two ways

1. Extending Java Thread class :-


Class need to extend the Thread class & Override the run() method.

Example :-

class MyThread extends Thread
{
public void run()
{
System.out.println("Important job running in MyThread");
}
}

But the problem with this approach is that class can not extend any more class - because In Java multiple inheritance is not permitted.

please read more about this in OOP - Inheritance concept


Note : run method can be overloaded in class. but only run() method(without argument) will be consider by JVM. Any other overridden method will needs to be called explicitly.

Example for defining a Thread by Extending Thread class

	class MyThread extends Thread 
	{
		public void run() //job of a thread
		{
			for (int i=0;i<10,i++ )
			{
				System.out.println("This is a new thread!");
			}
		}
	}
	class ThreadDemo
	{
		public static void main(String[] args)
		{
			MyThread t = new MyThread(); //Instantiation of a Thread
			t.start();// starting a thread
			{
				System.out.println("This is from main!");
			}
		}
	}

If multiple Threads are waiting for execution then the Thread which should be executed first is decided by ThreadScheduler. Thread scheduler is a part of JVM so we cannot predict its behaviour


Difference between function calls t.start() and t.run() :-



Performance Example of implement Runnable and extends Thread :-

 //Implement Runnable Interface...
 class ImplementsRunnable implements Runnable {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ImplementsRunnable : Counter : " + counter);
 }
}

//Extend Thread class...
class ExtendsThread extends Thread {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ExtendsThread : Counter : " + counter);
 }
}

//Use above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {

public static void main(String args[]) throws Exception {
    // Multiple threads share the same object.
    ImplementsRunnable rc = new ImplementsRunnable();
    Thread t1 = new Thread(rc);
    t1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t2 = new Thread(rc);
    t2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t3 = new Thread(rc);
    t3.start();

    // Creating new instance for every thread access.
    ExtendsThread tc1 = new ExtendsThread();
    tc1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc2 = new ExtendsThread();
    tc2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc3 = new ExtendsThread();
    tc3.start();
 }
}

	Output :- 
	ImplementsRunnable : Counter : 1
	ImplementsRunnable : Counter : 2
	ImplementsRunnable : Counter : 3
	ExtendsThread : Counter : 1
	ExtendsThread : Counter : 1
	ExtendsThread : Counter : 1
//different object created for each new counter is there

Overloading of run() :-


Overloading of run() can be done but thread class start() always calls no arg run() only.


Example - Overloading of run() in Java thread

	//overloading of run
	class MyThread extends Thread 
	{
		public void run()
		{
				System.out.println("This is from no arg run()");
		}
		public void run(int i)
		{
				System.out.println("This is from int arg run()");
		}
	}
	class ThreadDemo2
	{
		public static void main(String[] args)
		{
			MyThread t = new MyThread();
			t.start();
			System.out.println("This is from main!");
		}
	}
	
	output :- 
	This is from main!
	This is from no arg run()
	

What happens if we override start() ::::---


If we override start(), our start() will be executed like any ordinary method and no new Thread will be created.


example of override start() in Java thread

//override start
class MyThread extends Thread 
{
	public void start()
	{
		System.out.println("Start Method");
	}
	public void run()
	{
			System.out.println("This is from run()");
	}	
}
class ThreadDemo4
{
	public static void main(String[] args)
	{
		MyThread t = new MyThread();
		t.start(); //this will be called like a normal method, here no thread is created
		System.out.println("This is from main!");
	}
}
	Output :- 
	Start Method
	This is from main!


After starting of a thread, we should not try to restart it
i.e. we should not call start() on a thread which is already started. If we do so we would get “IllegalThreadStateException”


Defining a Thread by implementing Runnable interface


Class needs to implement runnable interface and override the run() method. Creating Thread in this way gives you flexibility to extend any class you like.

Example - Creating a thread by implementing Runnable interface

	class MyRunnable implements Runnable
	{
		public void run()
		{
			System.out.println("Child Thread!");
		}
	}
	class ThreadDemo3
	{
		public static void main(String[] args) 
		{
			MyRunnable r = new MyRunnable();
			Thread t = new Thread(r);
			t.start();
			System.out.println("Hello from main method!");
		}
	}

As you can see there is difference in Creating Thread object is different for both the cases.

Difference in Creating Thread object in Both Cases :-


Every thread of execution begins as an instance of class Thread. In any case Thread objects needs to be created before creating Thread of Execution.
Creating Thread object is different for both the cases.
In case of Extending Thread class you can directly initiate class with new keyword as it has extended Thread class itself.
In case of implimenting Runnable interface First created runnable class needs to be instatiated.

//Case - 1
//directly initiate class with new keyword.
MyThread t = new MyThread()

//Case - 2
//In case of implimenting Runnable interface. 
//First created runnable class needs to be instatiated.
MyRunnable r = new MyRunnable();

//Now pass this runnable object to Thread.
Thread t = new Thread(r);

If you create a thread using the no-arg constructor, the thread will call its own run(). This happened in first case(Extending Thread class)

But in case of Runnable Thread class needs to know that run method from class implementing runnnable interface needs to be invoked instead of run() from Thread class.
So we need to pass the class as argument to Thread. Single runnable instance can be passed to multiple Thread object.


Thread class constructors



To set and get name of the Thread


Every thing in java has some name, it may be default name generated by JVM or it may be a name explicitly provided by programmer.

Thread class defines following methods to get and set names of Thread.

Example of Setting and Getting name of thread class

//to get and set names of a thread
class MyThread extends Thread 
{
	public void run()
	{
			System.out.println("This is a new thread!");
	}
}
class ThreadDemo5
{
	public static void main(String[] args)
	{
		System.out.println(Thread.currentThread().getName()); //Main
		MyThread t = new MyThread();		
		System.out.println(t.getName()); //Thread-0
		//Now lets change the name of main
		Thread.currentThread().setName("javaEssential");
		System.out.println(Thread.currentThread().getName());
		//System.out.println(10/0);
	}
}

/* If you remove comment in line 19, you can observe error like
Exception in thread "javaEssential" java.lang.ArithmeticException: / by zero
at ThreadDemo5.main(ThreadDemo5.java:19)
Observe it says javaEssential not main, hence we successfully changed the name of the thread



Thread Priority in Java :-

Every Thread in Java has some priority. Valid range of priorities is from 1 to 10 where 1 is least and 10 is the highest priority.
Thread class defines the three constants to represents standard priorities.

Thread scheduler uses Thread Priorities while allocating processor and obviously the Thread which has high priority will get more chance to execute.

The default priority of main thread in java is 5 and for remaining threads the default priority will be inherited from parent to child.
We can change the priority of Threads by using following methods

Example program to set and get priorities of a Thread

class MyThread extends Thread 
{
	public void run()
	{
			System.out.println("This is a new thread!");
	}
}
class ThreadDemo6
{
	public static void main(String[] args)
	{
		System.out.println(Thread.currentThread().getPriority());
		MyThread t = new MyThread();
		System.out.println(t.getPriority());
		t.setPriority(Thread.MAX_PRIORITY);
	    System.out.println(t.getPriority());
		t.start();
		System.out.println("This is from main");
	}
}

Thread Sates :-

Diffrent states of Thread

join(), yield(), sleep() in Java


yield() method in java Threading


yield() causes to pause current executing thread to give chance for remaining waiting threads of same priority.
If there is no waiting thread or all waiting threads have a lesser priority then the same thread will continue its execution

yield() in Java :-

class MyThread extends Thread 
{
	public void run()
	{
		for (int i=0;i<10 ;i++ )
		{
			System.out.println("This is a new thread!");
		}
	}
}
class ThreadDemo7
{
	public static void main(String[] args)
	{
		MyThread t = new MyThread();
		t.start();
		Thread.currentThread().yield();
		for (int i=0;i<10 ;i++ )
		{
			System.out.println("This is from main!");
		}
	}
}

join() method in java :-


If a thread wants to wait untill completion of other Thread, then we need to use join() method.
Eg: If a thread t1 want to wait until the completion of t2, then it has to call t2.join(). Once thread executes t2.join() then t1 will immediately enter into a waiting stage until t2 Thread completes.
Three variants of join method


Example programs using join() method

or

How can we make sure main() is the last thread to finish in Java Program?


//demonstration of join() 
class MyThread extends Thread 
{
	public void run()
	{
		for (int i=0;i<10 ;i++ )
		{
		 System.out.println("Seetha Thread!");
			try
			{			 
			  Thread.sleep(100);
			}
			catch (InterruptedException e)
			{  }			
		}
	}
}
class ThreadDemo8
{
	public static void main(String[] args) throws InterruptedException
	{
		MyThread t = new MyThread();
		t.start();
		t.join(); // Main thread will wait untill completion of t
		for (int i=0;i<10 ;i++ )
		{
			System.out.println("Rama Thread!");		  
			    Thread.sleep(100);
			}
		}
	}
	

Example - Calling join method in child thread

//Calling  join() on child thread 
class MyThread extends Thread 
{
	static Thread mt;
	public void run() 
	{
	    try
			{
			mt.join();		
			for (int i=0;i<10 ;i++ )
				{
				System.out.println("Child Thread!");		  
				 Thread.sleep(100);
				}
			}
		catch(InterruptedException e) 
			{		}
	} }	
class ThreadDemo9
{
	public static void main(String[] args) throws InterruptedException
	{
		MyThread.mt = Thread.currentThread();
		MyThread t = new MyThread();
		t.start();
		for (int i=0;i<10 ;i++ )
		{
			System.out.println("Main Thread!");		  
		    Thread.sleep(100);
			}
		}
	}
	

if a thread calls join() on itself then the program will be hunged



sleep() in java :-


If we want a Thread to suspend it temporarily then we should call sleep() on it.

Example of Sleep() in java threading

package com.javaessential.threads;
 
import java.util.ArrayList;
import java.util.List;
 
public class MyThreadSuspend {
    public static void main(String a[]){
        List<ExmpThread> list = new ArrayList<ExmpThread>();
        for(int i=0;i<4;i++){
            ExmpThread et = new ExmpThread(i+10);
            list.add(et);
            et.start();
        }
        for(ExmpThread et:list){
            try {
                et.join();
            } catch (InterruptedException ex) { }
        }
    }
}
 
class ExmpThread extends Thread{
    private int suspendCount;
    public ExmpThread(int count){
        this.suspendCount = count;
    }
    public void run(){
        for(int i=0;i<50;i++){
            if(i%suspendCount == 0){
                try {
                    System.out.println("Thread Sleep: " + getName());
                    Thread.sleep(500);
                } catch (InterruptedException ex) { }
            }
        }
    }
}


Daemon Threads in Java

An example of Daemon Thread :-

class MyThread extends Thread 
{
	public void run()
	{
		for (int i=0;i<15 ;i++ )
		{
			System.out.println("Lazy thread - Daemon Thread !");
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{   }
		}
	}
}
class DaemonThreadExmpl
{
	public static void main(String[] args) throws InterruptedException
	{
		MyThread t = new MyThread();
		t.setDaemon(true); //Making my thread as Daemon
		t.start();
		t.sleep(5000);
		System.out.println("End of main!");
	}
}
 Output :- 
 
Lazy thread - Daemon Thread !
Lazy thread - Daemon Thread !
Lazy thread - Daemon Thread !
Lazy thread - Daemon Thread !
Lazy thread - Daemon Thread !
Lazy thread - Daemon Thread !
End of main!
 
// NOTE : "Lazy thread - Daemon Thread !" this might be printed 5 or 6 time no need to worry 

If u want to make a user thread as Daemon, it must not be started otherwise it will throws IllegalThreadStateException.



Blocking Queues


A blocking queue is a queue that blocks when you try to dequeue from it and the queue is empty, or if you try to enqueue items to it and the queue is already full.

A thread trying to dequeue from an empty queue is blocked until some other thread inserts an item into the queue.
A thread trying to enqueue an item in a full queue is blocked until some other thread makes space in the queue, either by dequeuing one or more items or clearing the queue completely.


Blocking Queue Implementation :-


public class BlockingQueue {

  private List queue = new LinkedList();
  private int  limit = 10;

  public BlockingQueue(int limit){
    this.limit = limit;
  }


  public synchronized void enqueue(Object item)
  throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait();
    }
    if(this.queue.size() == 0) {
      notifyAll();
    }
    this.queue.add(item);
  }


  public synchronized Object dequeue()
  throws InterruptedException{
    while(this.queue.size() == 0){
      wait();
    }
    if(this.queue.size() == this.limit){
      notifyAll();
    }

    return this.queue.remove(0);
  }

}

Notice how notifyAll() is only called from enqueue() and dequeue() if the queue size is equal to the size bounds (0 or limit).
If the queue size is not equal to either bound when enqueue() or dequeue() is called, there can be no threads waiting to either enqueue or dequeue items.



Click here to access OOp's Concept

feel free to ask any of your doubts