A Complete MultiThreading Tutorial In Java

Multithreading in Java is a process of executing multiple threads simultaneously. A thread is the smallest unit of the processing. Multithreading and Multiprocessing, both are used to achieve multitasking.

Introduction

 
The process of executing multiple threads concurrently is called multithreading in Java. This article will explain Multithreading and how multithreading works in Java with code example. In Java, threads use a shared memory location. 
 

What is Thread in Java?

 
A thread is a lightweight small process or the smallest unit of the processing, which can run concurrently with the other threads of the same process.
 
Threads are independent because they all have a separate path of execution due to which if an exception occurs in one thread, it doesn't affect the execution of other threads. All the threads of a process share the common memory area. The process of executing multiple threads is called multithreading in Java.
 
Let's understand with the figure, given below.
java-threads 
In the figure, a thread is executed inside the process and the context-switching between the threads. Here the multiple processes in the OS and the single process can have multiple threads but only one thread executed at a time.
 
Multithreading is a procedure of executing the multiple threads at the same time. Multiprocessing and multithreading are used to achieve multitasking in Java. Saving memory and context-switching between the threads takes less time than the process. Multithreading is mainly used in games, animation, etc.
 

What are the Advantages of Multithreading?

  • The threads are independent due to which we can perform multiple operations at the same time.
  • We can perform many operations simultaneously, so it saves time.
  • The Threads don't affect other threads if an exception occurs in a single thread.
  • Better use of CPU resources.
  • Decrease the cost of maintenance.
  • Better use of cache storage by utilization of resources.

What are the Disadvantages of Multithreading?

  • Multiple threads can interfere with each other when sharing hardware resources such as caches or transaction lookaside buffers(TLBs). 
  • The execution time of a single thread can be degraded, even when only one thread is executing.
  • Complex debugging and testing process.
  • Unpredictable results.

Why we use Multithreading in Java?

 
We use multithreading in Java for achieving Multitasking. 
 

What is Multitasking?

 
Multitasking is the process of executing multiple tasks at the same time. We use multitasking to utilize the CPU. 
 
Multitasking can be achieved in two ways. Which are:
 
Process-based Multitasking  
 
Process-based multitasking means Multiprocessing, in this, every process has its own memory address and every process allocate a separate memory area. 
 
The process is heavy-weight. Cost of communication between the process is very high. Switching from one process to another process requires some time to save and load the registers, memory maps, updates, lists, etc.
 
Thread-based Multitasking
 
Thread-based multitasking means Multithreading. in which all the threads share the same address space.
 
Thread is light-weight. Cost of communication between the threads is very low. At least one process is required for each thread.
 

What is thread life-cycle in Java? 

 
A thread goes through many different stages in its life cycle. For example, a thread is born, thread start, thread run, and then thread die. The life cycle of the thread is controlled by JVM in Java. For a better understanding of the thread, we explain it in the five states.
 
java-thread-lifecycle
New
 
A new state is the first state of the thread. The thread is in new state if we create an object of the Thread class but before the invocation of start() method. 
 
Runnable 
 
After a new thread starts, the thread is in the second state after the invocation of start() method, but the scheduler has not selected it to be in the running thread.
 
Running 
 
The third state is running. The thread is in running state if the thread scheduler has selected it.
 
Non-Runnable (Blocked) 
 
The fourth state is non-runnable(blocked). This is the state when the thread is alive but is currently not eligible to run. 
 
Terminated 
 
The last state of a thread is terminated. A thread is in the terminated state when its run() method exits. 
 

How threads are created in Java? 

 
Threads are created in java in two ways, first by extending the Thread class and second by implementing the Runnable interface by any Java class.
 
How many ways create a thread in Java?
 
There are two ways to create a thread in Java multithreading.
  1. By Extending Thread class 
  2. By implementing Runnable method 

What is Thread class in Multithreading? 

 
Thread class provides many constructors and methods to create and perform many operations on a  thread. Thread class extends an Objects class and implements Runnable interface in Java multithreading.
 
Constructors of Thread class
 
1. Thread()

Allocates a new Thread object. The complete program is listed below.
  1. public class ThreadConstructor extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("This is example of Thread Constructor");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadConstructor t = new ThreadConstructor();  
  9.         t.start();  
  10.     }  

The output of the following code generates the following output.

thread-constructor

2. Thread(String name)

Allocates a new Thread object. The complete program is listed below.
  1. public class ThreadConstructor1 extends Thread{  
  2.   
  3.   
  4.     String tname;  
  5.   
  6.     ThreadConstructor1(String tname) {  
  7.         this.tname = tname;  
  8.     }  
  9.   
  10.     public void run() {  
  11.         System.out.println(tname);  
  12.     }  
  13.   
  14.     public static void main(String args[]) {  
  15.         ThreadConstructor1 t = new ThreadConstructor1("First Thread");  
  16.         t.start();  
  17.     }  

The output of the following code generates the following output.

thread-constructor1

3. Thread(Runnable r)

Allocates a new Thread object. The complete program is listed below.
  1. public class ThreadConstructor2 implements Runnable {  
  2.   
  3.     public void run() {  
  4.         System.out.println("This is the example of Thread(Runnable target) constructor");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadConstructor2 s = new ThreadConstructor2();  
  9.         Thread t = new Thread(s);  
  10.         t.start();  
  11.     }  

The output of the following code generates the following output.

thread-constructor2
4. Thread(Runnable r, String name)
 
Allocates a new Thread object. The complete program is listed below.
  1. public class ThreadConstructor3 implements Runnable {  
  2.   
  3.     ThreadConstructor3() {  
  4.     }  
  5.   
  6.     public void run() {  
  7.         System.out.println("This is the example of Thread(Runnable target, String name) constructor");  
  8.     }  
  9.   
  10.     public static void main(String args[]) {  
  11.         ThreadConstructor3 s = new ThreadConstructor3();  
  12.         Thread t = new Thread(s, "CsharpCorner");  
  13.   
  14.         t.start();  
  15.     }  

The output of the following code generates the following output.

thread-constructor3
 

Methods of Thread class

 
1. public void run()

This method is used to perform an action for a thread. The complete program is listed below.
  1. public class ThreadRunMethod extends Thread {  
  2.   
  3.   
  4.     public void run() {  
  5.         System.out.println("This is the example of run() method");  
  6.     }  
  7.   
  8.     public static void main(String args[]) {  
  9.         ThreadRunMethod t = new ThreadRunMethod();  
  10.         t.start();  
  11.     }  

The output of the following code generates the following output.

thread-run-method

2. public void Thread.start()

This method is used to start the execution of the thread. JVM calls the run() method to start the thread. The complete program is listed below.
  1. public class ThreadStartMethod extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("This is the example of start() method");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadStartMethod s = new ThreadStartMethod();  
  9.         s.start();  
  10.     }  

The output of the following code generates the following output.

thread-start-method

3. public void Thread.sleep(long milliseconds)

The Thread class sleep() method is used to sleep a thread for a particular duration of time. If one thread sleeps for the specified time then the thread scheduler picks up other thread and so on. The complete program is listed below.
  1. public class ThreadSleepMethod extends Thread {  
  2.   
  3.     public void run() {  
  4.         for (int i = 0; i < 5; i++) {  
  5.             try {  
  6.                 Thread.sleep(1000);  
  7.             } catch (InterruptedException e) {  
  8.                 System.out.println(e);  
  9.             }  
  10.             System.out.println(i);  
  11.         }  
  12.     }  
  13.   
  14.     public static void main(String args[]) {  
  15.         ThreadSleepMethod t1 = new ThreadSleepMethod();  
  16.         ThreadSleepMethod t2 = new ThreadSleepMethod();  
  17.         t1.start();  
  18.         t2.start();  
  19.     }  

The output of the following code generates the following output.

thread-sleep-method1

4. public void Thread.join()

The join method is used to wait for a thread to die. The complete program is listed below.
  1. public class ThreadJoinMethod1 extends Thread {  
  2.   
  3.     public void run() {  
  4.         for (int i = 0; i <= 3; i++) {  
  5.             try {  
  6.                 Thread.sleep(1000);  
  7.             } catch (Exception e) {  
  8.                 System.out.println(e);  
  9.             }  
  10.             System.out.println(i);  
  11.         }  
  12.     }  
  13.   
  14.     public static void main(String args[]) {  
  15.         ThreadJoinMethod1 t1 = new ThreadJoinMethod1();  
  16.         ThreadJoinMethod1 t2 = new ThreadJoinMethod1();  
  17.         ThreadJoinMethod1 t3 = new ThreadJoinMethod1();  
  18.         t1.start();  
  19.         try {  
  20.             t1.join();  
  21.         } catch (Exception e) {  
  22.             System.out.println(e);  
  23.         }  
  24.   
  25.         t2.start();  
  26.         t3.start();  
  27.   
  28.         System.out.println("This is Thread join() method example");  
  29.     }  

The output of the following code is listed below.

thread-join-method

5. public void Thread.join(long milliseconds)
 
This method is used to waits for a thread to die for a specified millisecond. The complete program is listed below.
  1. public class ThreadJoinMethod2 extends Thread {  
  2.   
  3.     public void run() {  
  4.         for (int i = 0; i <= 3; i++) {  
  5.             try {  
  6.                 Thread.sleep(700);  
  7.             } catch (Exception e) {  
  8.                 System.out.println(e);  
  9.             }  
  10.             System.out.println(i);  
  11.         }  
  12.     }  
  13.   
  14.     public static void main(String args[]) {  
  15.         ThreadJoinMethod2 t1 = new ThreadJoinMethod2();  
  16.         ThreadJoinMethod2 t2 = new ThreadJoinMethod2();  
  17.         ThreadJoinMethod2 t3 = new ThreadJoinMethod2();  
  18.         t1.start();  
  19.         try {  
  20.             t1.join(1000);  
  21.         } catch (Exception e) {  
  22.             System.out.println(e);  
  23.         }  
  24.         t2.start();  
  25.         t3.start();  
  26.         System.out.println("This is Thread join() method example");  
  27.   
  28.     }  

The output of the following code generated the following output.

thread-join-method2

6. public void Thread.currentThread()
 
The thread class static method currentThread() returns the reference of the Thread object that calls this method. The complete program is listed below.
  1. public class ThreadCurrentMethod extends Thread {    
  2.     
  3.         @Override    
  4.         public void run() {    
  5.             Thread t = Thread.currentThread();    
  6.             String threadName = t.getName();    
  7.             System.out.println("Inside run() method:  " + threadName);    
  8.         }    
  9.     
  10.         public static void main(String[] args) {    
  11.             ThreadCurrentMethod ct = new ThreadCurrentMethod ();    
  12.             ct.start();    
  13.     
  14.             Thread t = Thread.currentThread();    
  15.             String threadName = t.getName();    
  16.             System.out.println("Inside  main() method:  " + threadName);    
  17.         }    
  18.     }   
The output of the following code generates the following output.

thread-current-method.

7. public String Thread.getName()

This method is used to return the name of the thread. The complete program is listed below.
  1. public class ThreadGetnameMethod extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("threads running fast...");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadGetnameMethod t1 = new ThreadGetnameMethod();  
  9.   
  10.         System.out.println("Name of thread 1:" + t1.getName());  
  11.         t1.start();  
  12.   
  13.     }  

The output of the following code generates the following output.

thread-getname-method

8. public String Thread.setName(String name)

This method is used to change the name of the thread. The complete program is listed below.
  1. public class ThreadSetnameMethod extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("threads running fast...");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadSetnameMethod t1 = new ThreadSetnameMethod();  
  9.         System.out.println("Name of thread 1: " + t1.getName());  
  10.         t1.start();  
  11.   
  12.         t1.setName("Strong Thread");  
  13.         System.out.println("After changing name of thread 1:" + t1.getName());  
  14.     }  

The output of the code generates the following output.

thread-setname-method

9. public int Thread.currentThread().getPriority()

This method is used to return the priority of the thread. The complete program is listed below.
  1. public class ThreadGetPriorityMethod extends Thread {  
  2.   
  3.     public void run() {  
  4.   
  5.         System.out.println("Current thread priority is:" + Thread.currentThread().getPriority());  
  6.     }  
  7.   
  8.     public static void main(String args[]) {  
  9.         ThreadGetPriorityMethod g = new ThreadGetPriorityMethod();  
  10.         g.start();  
  11.     }  

The output of the following code generates the following output.

thread-getpriority-method

10. public void Thread.currentThread().setPriority(int priority)

This method is used to change the priority of the thread. The complete program is listed below.
  1. public class ThreadSetPriorityMethiod extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("Current thread priority is:" + Thread.currentThread().getPriority());  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadSetPriorityMethiod s = new ThreadSetPriorityMethiod();  
  9.         s.setPriority(8);  
  10.         s.start();  
  11.     }  

The output of the following code generates the following output.

thread-setPriority-method

What is the Runnable interface in Java? 

 
The runnable interface must be implemented by any class, whose instances are intended to be executed by a thread. The Runnable interface has only one run() method.
 
public void run()
 
This method is used to perform an action for a thread. The complete program is listed below.
  1. public class RunnableRunMethod implements Runnable {  
  2.   
  3.     @Override  
  4.     public void run() {  
  5.         System.out.println("This is the example of Runnable interface run() method");  
  6.     }  
  7.   
  8.     public static void main(String[] args) {  
  9.         RunnableRunMethod m = new RunnableRunMethod();  
  10.         Thread t = new Thread(m);  
  11.         t.start();  
  12.     }  
  13.  
The output of the following code generates the following output.
 
runnable-run-method 
 

How to start a thread in Java?

 
start() method is used to start a newly created thread. It performs may tasks, Which are-
  • A new thread start.
  • The thread shifts from the new state to the runnable state.
  • If the thread gets a chance to execute, its target run() method will run. 
The complete program is listed below. 
  1. public class ThreadExample extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("This is example of how to start a Thread in Java.");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadExample t = new ThreadExample();  
  9.         t.start();  
  10.     }  

The output of the following code generates the following output.
 
thread-example 
 

Can We start a thread twice?

 
No, we cannot start a thread twice, after starting a thread, it can never be started again. If we do then all IllegalThreadStateException is thrown. In this case, the thread will run once but next time, it will throw an exception. The complete program is listed below.
  1. public class StartThreadTwice extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("we can not start a thread twice in a program");  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadExample t1 = new ThreadExample();  
  9.         t1.start();  
  10.         t1.start();  // Exception  
  11.     }  
  12. }  
The output of the following code generates the following output.
 
start-thread-twice
 

What is Thread scheduler in Java? 

 
The thread scheduler is the part of JVM, which decides which thread should run. There is no assurance that which runnable thread will be chosen to run by the scheduler. Any thread in the runnable state can be chosen by the scheduler to be the one and only running thread and if a thread is not in a runnable state, then it cannot be chosen to be the current running thread. Some method can influence the scheduler to some extent and we can't control the behaviour of the thread scheduler. Only one thread at a time can run in a single process in Java.
 
The thread scheduler generally uses preemptive scheduling or time-slicing scheduling to schedule the threads in Java. 
 

Difference between Preemptive Scheduling and Time-slicing scheduling

 
Preemptive Scheduling Time-slicing Scheduling
Under the preemptive scheduling, the highest priority tasks perform until it enters the waiting or dead state or a higher priority task comes into existence. Under the time-slicing scheduling, a task performs for a predefined a slice of time and then reenters the pool of ready tasks. The thread scheduler then decides which task should execute next, based on the priority and other factors.
 

A priority of Thread in Java 

 
Thread priorities are represented in the number of 1 to 10. Thread scheduler schedules the threads, according to their priority, which is referred to as preemptive scheduling. There is no guarantee because it fully depends on JVM specification that which scheduling, it chooses.
 
Each thread has a priority. 
 
Three constants are defined in Thread class,  
  1. public static int MIN_PRIORITY
  2. public static int NORM_PRIORITY
  3. public static int MAX_PRIORITY
By default thread priority is NORM_PRIORITY(5)
 
The value of MIN_PRORITY is 0 and MAX_PRIORITY is 10. 
 
The complete program is given below.
  1. public class ThreadPriority extends Thread {  
  2.     public void run() {  
  3.         System.out.println("Current thread name is:" + Thread.currentThread().getName());  
  4.         System.out.println("Current thread priority is:" + Thread.currentThread().getPriority());  
  5.     }  
  6.   
  7.     public static void main(String args[]) {  
  8.         ThreadPriority p1 = new ThreadPriority();  
  9.         p1.setPriority(Thread.MIN_PRIORITY);  
  10.         p1.start();  
  11.     }  

The output of the following code generates the following output.
 
thread-priority
 

What is Thread Pool in Java?

 
Thread Pool is a group of worker threads, which are waiting for the job and it can be reused many times.
 
A group of fixed size threads are created in a thread pool. A thread from the thread pool is selected and is assigned a job by the Service provider. After completion of his job, the thread is contained in the thread pool again.
 

What are the usages of thread pool in Java?

 
Thread pool mainly used in JSP and Servlets in Java, which web or Servlets container creates a thread pool to process the request.
 
It saves time and better performance because there is no need to create a new thread. The complete program is listed below.
 
Step 1
 
First, we create a ThreadPoolExample Java class and implements Runnable interface. 
  1. class ThreadPoolExample implements Runnable {  
  2.     private String thread;  
  3.   
  4.     public ThreadPoolExample(String t) {  
  5.         this.thread = t;  
  6.     }  
  7.   
  8.     public void run() {  
  9.         System.out.println(Thread.currentThread().getName() + " Start thread = " + thread);  
  10.         processmessage();//sleeps the thread for 2 seconds  
  11.         System.out.println(Thread.currentThread().getName() + " End ");//prints thread name  
  12.     }  
  13.   
  14.     private void processmessage() {  
  15.         try {  
  16.             Thread.sleep(1500);  
  17.         } catch (InterruptedException e) {  
  18.             e.printStackTrace();  
  19.         }  
  20.     }  
  21. }  
Step 2
 
Second we create the ThreadPoolTest Java class for tesing the working of the threadpool.
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3.   
  4. public class ThreadPoolTest {  
  5.     public static void main(String[] args) {  
  6.         ExecutorService e = Executors.newFixedThreadPool(3);//creating a pool of 3 threads  
  7.         for (int i = 0; i <= 6; i++) {  
  8.             Runnable t = new ThreadPoolExample("" + i);  
  9.             e.execute(t);  
  10.         }  
  11.         e.shutdown();  
  12.         while (!e.isTerminated()) {  
  13.         }  
  14.         System.out.println("All threads are finish");  
  15.     }  
  16. }  
The output of the code generates the following output.
 
threadpool 
 

What is the ThreadGroup class in Java?

 
A group of multiple threads in a single object is called a ThreadGroup class in Java. With the help of ThreadGroup class, we can suspend, resume or interrupt a group of threads with a single method call. 
 
ThreadGroup is implemented by java.lang.ThreadGroup class. The complete program is listed below.
  1. public class ThreadGroupExample implements Runnable {  
  2.     public void run() {  
  3.         System.out.println(Thread.currentThread().getName());  
  4.     }  
  5.   
  6.     public static void main(String[] args) {  
  7.         ThreadGroupExample obj = new ThreadGroupExample();  
  8.         ThreadGroup tg = new ThreadGroup("Main ThreadGroup");  
  9.         Thread t1 = new Thread(tg, obj, "thread1");  
  10.         t1.start();  
  11.         Thread t2 = new Thread(tg, obj, "thread2");  
  12.         t2.start();  
  13.         Thread t3 = new Thread(tg, obj, "thread3");  
  14.         t3.start();  
  15.         System.out.println("Name of ThreadGroup : " + tg.getName());  
  16.         tg.list();  
  17.     }  
  18. }  
The output of the following code generates the following output.
 
threadgroup 
 
Note
In this example, we create three threads which belong to one group. Here, tg is the ThreadGroup name, The ThreadGroupExample class implements Runnable interface and thread1, thread2, thread3 are the threads name. 
 

What is Daemon Thread in Java? 

 
Daemon thread is a service provider, which provides the services to the user thread. It is a low priority thread, which runs in the background to perform the tasks. Its life depends on the mercy of the user threads, i.e When all the threads die, JVM automatically terminates this thread. 
 
There are many Java daemon threads running automatically such as garbage collection(gc) finalizer etc.
 
Some important points for Daemon Thread,
  • It provides the services to the user thread for the background supporting tasks. It has no role in life than to serve the user thread. 
  • Its life fully depends on user threads.
  • It is a low priority thread. 

Why JVM terminates the Daemon thread if there is no user thread? 

 
The main purpose of the daemon thread is providing the services to the user threads for the background supporting tasks due to which if there is no user thread, JVM terminates Daemon thread.
 
The complete program of a daemon thread is listed below. 
  1. public class DaemonThreadExample extends Thread {  
  2.         public void run() {  
  3.             if (Thread.currentThread().isDaemon()) {//checking for a daemon thread  
  4.                 System.out.println("I am Daemon thread");  
  5.             } else {  
  6.                 System.out.println("I am User thread");  
  7.             }  
  8.         }  
  9.   
  10.         public static void main(String[] args) {  
  11.             DaemonThreadExample t1 = new DaemonThreadExample();  
  12.             DaemonThreadExample t2 = new DaemonThreadExample();  
  13.             t1.setDaemon(true);//it's a daemon thread  
  14.             t1.start();  
  15.             t2.start();  
  16.         }  
  17.     }  
The output of the code generates the following output.
 
Daemon-thread-example
 
If we want to create a User-defined Daemon thread, it should not be started, else it will throw an exception IllegalThreadStateException. The complete program of User-defined Daemon thread is listed below. 
  1. public class UserDefinedDaemon extends Thread {  
  2.     public void run() {  
  3.         System.out.println("Name: " + Thread.currentThread().getName());  
  4.         System.out.println("Daemon: " + Thread.currentThread().isDaemon());  
  5.     }  
  6.   
  7.     public static void main(String[] args) {  
  8.         UserDefinedDaemon t1 = new UserDefinedDaemon();  
  9.         t1.start();  
  10.         t1.setDaemon(true);//throw exception  
  11.     }  
  12. }  
The output of the following code generates the following output.
 
user-defined-daemon 
 

How to perform a single task by multiple threads?

 
If we want to perform a single task by many threads, we need to use only one run() method. The complete program is listed below. 
  1. public class MultipleThreadsingleTask extends Thread{  
  2.     public void run() {  
  3.         System.out.println("Task one is start now..");  
  4.     }  
  5.   
  6.     public static void main(String args[]) {  
  7.         MultipleThreadsingleTask mt1 = new MultipleThreadsingleTask();  
  8.         MultipleThreadsingleTask mt2 = new MultipleThreadsingleTask();  
  9.         MultipleThreadsingleTask mt3 = new MultipleThreadsingleTask();  
  10.         mt1.start();  
  11.         mt2.start();  
  12.         mt3.start();  
  13.     }  

The output of the following code generates the following output.
 
multiple-thread-singletask 
 
Note
In the example, we created MultipleThreads class extends Thread class and perform a single task through the multiple threads.
  

How to perform multiple tasks by multiple threads?

 
If we want to perform multiple tasks by multiple threads, we need to use multiple run() method. The complete program is listed below. 
  1. class Multi1 extends Thread {  
  2.   
  3.     public void run() {  
  4.         System.out.println("Task one is start now...");  
  5.     }  
  6. }  
  7.   
  8. class Multi2 extends Thread {  
  9.     public void run() {  
  10.         System.out.println("Task two is start now...");  
  11.     }  
  12. }  
  13.   
  14. public class MultipleThreadsMultipleTask {  
  15.     public static void main(String args[]) {  
  16.         Multi1 t1 = new Multi1();  
  17.         Multi2 t2 = new Multi2();  
  18.   
  19.         t1.start();  
  20.         t2.start();  
  21.     }  

The output of the following code generates the following output.
 
multiple-thread-multiple-task 
 

How to use Anonymous class with Runnable interface?

 
The classes which have no name are called Anonymous classes in Java. We can declare and initiate them at the same time. The complete program is listed below. 
  1. public class AnonymousClassExample {  
  2.   
  3.     public static void main(String args[]) {  
  4.           
  5.         Runnable r1 = new Runnable() {  
  6.   
  7.             public void run() {  
  8.                 System.out.println("Task one is start now...");  
  9.             }  
  10.         };  
  11.         Runnable r2 = new Runnable() {  
  12.               
  13.             public void run() {  
  14.                 System.out.println("Task two is start now...");  
  15.             }  
  16.         };  
  17.           
  18.         Thread t1 = new Thread(r1);  
  19.         Thread t2 = new Thread(r2);  
  20.         t1.start();  
  21.         t2.start();  
  22.     }  
  23. }  
The output of the following code generates the following output.
 
anonymous-class-example 
 

How to use Anonymous class that extends Thread class?

 
The complete program of the anonymous class that extends Thread class in Java. 
  1. public class AnonymousClassExample {  
  2.   
  3.     public static void main(String args[]) {  
  4.   
  5.         Thread t1 = new Thread() {  
  6.               
  7.             public void run() {  
  8.                 System.out.println("Task one is start now...");  
  9.             }  
  10.         };  
  11.         Thread t2 = new Thread() {  
  12.   
  13.             public void run() {  
  14.                 System.out.println("Task two is start now...");  
  15.             }  
  16.         };  
  17.   
  18.         t1.start();  
  19.         t2.start();  
  20.     }  
  21. }  
The output of the following code generates the following output.
 
anonymous-class-thread
 

What happens when we call run() method instead of start() method in multithreading? 

 
Every thread starts in a separate call stack. Calling the run() method from the main thread, followed by the run() method goes on the present call stack rather than at the beginning of the new call stack.
 
There will be no context-switching between the threads. The complete program is listed below. 
  1. public class RunInsteadOfStart extends Thread {  
  2.     public void run() {  
  3.   
  4.         for (int i = 0; i < 3; i++) {  
  5.             try {  
  6.                 Thread.sleep(500);  
  7.             } catch (InterruptedException e) {  
  8.                 System.out.println(e);  
  9.             }  
  10.             System.out.println(i);  
  11.         }  
  12.     }  
  13.   
  14.     public static void main(String args[]) {  
  15.   
  16.         RunInsteadOfStart t1 = new RunInsteadOfStart();  
  17.         RunInsteadOfStart t2 = new RunInsteadOfStart();  
  18.         t1.run();  
  19.         t2.run();  
  20.     }  

The output of the following code generates the following output.
 
run-instead-start
 
Note
In this example, we can see that there is no context-switching because here t1 and t2 will treat as a normal object and not a thread object.
 

What is Thread Synchronization?

 
In Java, synchronization is the capacity to control the access of the multiple threads to any shared resources. It is a good option when we want to allow one thread to access the shared resources. 
  
There are 2 types of Thread synchronization.
 
1) Mutual exclusive
 
Mutual exclusive helps to keep the threads from a interfere with one another as a sharing data. This can be done in three ways.
 
a. By synchronized method

When we create any method as synchronized, it is called a synchronized method. Synchronized method locks an object for any shared resources. When a thread calls a synchronized method, it automatically gets the lock for that object and frees it when the thread completes its task. The complete program is listed below. 
  1. class Customer {  
  2.     int amount = 10000;  
  3.   
  4.     synchronized void withdraw(int amount) {  
  5.         System.out.println("going to withdraw...");  //Synchronized Method
  6.   
  7.         if (this.amount < amount) {  
  8.             System.out.println("Less balance; waiting for deposit...");  
  9.             try {  
  10.                 wait();  
  11.             } catch (Exception e) {  
  12.   
  13.             }  
  14.         }  
  15.         this.amount -= amount;  
  16.         System.out.println("withdraw completed...");  
  17.     }  
  18.   
  19.     synchronized void deposit(int amount) {  
  20.         System.out.println("going to deposit...");  
  21.         this.amount += amount;  
  22.         System.out.println("deposit completed... ");  
  23.         notify();  
  24.     }  
  25. }  
  26.   
  27. public class SynchronizedMethodExample {  
  28.     public static void main(String args[]) {  
  29.         final Customer c = new Customer();  
  30.   
  31.         new Thread() {  
  32.             public void run() {  
  33.                 c.withdraw(15000);  
  34.             }  
  35.         }.start();  
  36.   
  37.         new Thread() {  
  38.             public void run() {  
  39.                 c.deposit(10000);  
  40.             }  
  41.         }.start();  
  42.   
  43.     }  

The output of the following code generates the following output.
 
synchronized-method
 
b. By synchronized block

A block in java is a group of one or more statements enclosed in braces. when we used synchronized keyword with a block, it is called synchronized block. The complete program is listed below.
  1. class Table {  
  2.   
  3.     void printTable(int n) {  
  4.         synchronized (this) {//synchronized block  
  5.             for (int i = 1; i <= 5; i++) {  
  6.                 System.out.println(n * i);  
  7.                 try {  
  8.                     Thread.sleep(400);  
  9.                 } catch (Exception e) {  
  10.                     System.out.println(e);  
  11.                 }  
  12.             }  
  13.         }  
  14.     }//end of the method  
  15. }  
  16.   
  17. class MyThreadClass1 extends Thread {  
  18.     Table t;  
  19.   
  20.     MyThreadClass1(Table t) {  
  21.         this.t = t;  
  22.     }  
  23.   
  24.     public void run() {  
  25.         t.printTable(5);  
  26.     }  
  27.   
  28. }  
  29.   
  30. class MyThreadClass2 extends Thread {  
  31.     Table t;  
  32.   
  33.     MyThreadClass2(Table t) {  
  34.         this.t = t;  
  35.     }  
  36.   
  37.     public void run() {  
  38.         t.printTable(100);  
  39.     }  
  40. }  
  41.   
  42. public class SynchronizedBlockExample {  
  43.   
  44.     public static void main(String args[]) {  
  45.         Table obj = new Table();//only one object  
  46.         MyThreadClass1 t1 = new MyThreadClass1(obj);  
  47.         MyThreadClass2 t2 = new MyThreadClass2(obj);  
  48.         t1.start();  
  49.         t2.start();  
  50.     }  

The output of the following code generates the following output.
 
synchronized-block-example
 
c. By static synchronized

If we make any static method as synchronized, the lock will be on the class not on the object. The complete program is listed below.
  1. class PrintTable {  
  2.     public synchronized static void printTable(int n) {  
  3.         System.out.println("Table of " + n);       // static Synchroized
  4.         for (int i = 1; i <= 10; i++) {  
  5.             System.out.println(n * i);  
  6.             try {  
  7.                 Thread.sleep(500);  
  8.             } catch (Exception e) {  
  9.                 System.out.println(e);  
  10.             }  
  11.         }  
  12.     }  
  13. }  
  14.   
  15. class MyThread1 extends Thread {  
  16.     public void run() {  
  17.         PrintTable.printTable(2);  
  18.     }  
  19. }  
  20.   
  21. public class StaticSynchronizedExample {  
  22.     public static void main(String args[]) {  
  23.   
  24.         //creating threads.  
  25.         MyThread1 t1 = new MyThread1();  
  26.           
  27.         //start threads.  
  28.         t1.start();  
  29.     }  

The output of the following code generates the following output.

static-synchronized
 

Cooperation (interthread communication)

 
Cooperation (interthread communication) is all about allowing synchronized threads communicates with each other. It is a mechanism in which a thread is paused running in its critical section and another thread is allowed to enter in the same critical section to be executed. 
 
Java provides benefits of avoiding thread pooling using interthread communication. The complete program of interthread communication is listed below.
  1. class Messages {  
  2.     boolean flag = false;  
  3.   
  4.     public synchronized void Question(String msg) {  
  5.         if (flag) {  
  6.             try {  
  7.                 wait();  
  8.             } catch (InterruptedException e) {  
  9.                 e.printStackTrace();  
  10.             }  
  11.         }  
  12.         System.out.println(msg);  
  13.         flag = true;  
  14.         notify();  
  15.     }  
  16.   
  17.     public synchronized void Answer(String msg) {  
  18.         if (!flag) {  
  19.             try {  
  20.                 wait();  
  21.             } catch (InterruptedException e) {  
  22.                 e.printStackTrace();  
  23.             }  
  24.         }  
  25.   
  26.         System.out.println(msg);  
  27.         flag = false;  
  28.         notify();  
  29.     }  
  30. }  
  31.   
  32. class T1 implements Runnable {  
  33.     Messages m;  
  34.     String[] s1 = {"Hi""How are you ?""I am also doing fine!"};  
  35.   
  36.     public T1(Messages m1) {  
  37.         this.m = m1;  
  38.         new Thread(this"Question").start();  
  39.     }  
  40.   
  41.     public void run() {  
  42.         for (int i = 0; i < s1.length; i++) {  
  43.             m.Question(s1[i]);  
  44.         }  
  45.     }  
  46. }  
  47.   
  48. class T2 implements Runnable {  
  49.     Messages m;  
  50.     String[] s2 = {"Hi""I am good, what about you?""Great!"};  
  51.   
  52.     public T2(Messages m2) {  
  53.         this.m = m2;  
  54.         new Thread(this"Answer").start();  
  55.     }  
  56.   
  57.     public void run() {  
  58.         for (int i = 0; i < s2.length; i++) {  
  59.             m.Answer(s2[i]);  
  60.         }  
  61.     }  
  62. }  
  63.   
  64. public class InterThreadCommunicationExample {  
  65.     public static void main(String[] args) {  
  66.         Messages m = new Messages();  
  67.         new T1(m);  
  68.         new T2(m);  
  69.     }  

The output of the following code generates the following output.
 
inter-thread-communication 
 

What is Lock Concept in Multithreading?

 
Synchronization is built around an internal entity called the lock or monitor. All objects have a lock associated with it. By rule, a thread that needs consistent access to an object's fields to get the object's lock before accessing them and release the lock, when it's done with them. Since Java 5 the package java.util.concurrent.locks contain many lock implementations.
 
The complete program is listed below.
  1. class A {  
  2.     void print(int n) {  
  3.         for (int i = 1; i <= 5; i++) {  
  4.             System.out.println(n * i);  
  5.             try {  
  6.                 Thread.sleep(1000);  
  7.             } catch (Exception e) {  
  8.                 System.out.println(e);  
  9.             }  
  10.         }  
  11.     }  
  12. }  
  13. class MyThreadLock1 extends Thread {  
  14.     A a;  
  15.     MyThreadLock1(A a) {  
  16.         this.a = a;  
  17.     }  
  18.     public void run() {  
  19.         a.print(1);  
  20.     }  
  21. }  
  22. class MyThreadLock2 extends Thread {  
  23.     A a;  
  24.   
  25.     MyThreadLock2(A a) {  
  26.         this.a = a;  
  27.     }  
  28.     public void run() {  
  29.         a.print(100);  
  30.     }  
  31. }  
  32. public class LockConceptExample {  
  33.     public static void main(String args[]) {  
  34.         A obj = new A();  
  35.         MyThreadLock1 t1 = new MyThreadLock1(obj);  
  36.         MyThreadLock2 t2 = new MyThreadLock2(obj);  
  37.         t1.start();  
  38.         t2.start();  
  39.     }  

The output of the following code generates the following output.
 
lock-concept
 

What is Thread Deadlock in Java?

 
Deadlock is a situation of complete Lock when no thread can complete its execution because lack of resources. Deadlock occurs when multiple threads need same locks but obtain them in a different order. Since both threads are waiting for each other to release the lock, this condition is called deadlock.
 
java-thread-deadlock
The complete program is listed below.
  1. class Pen{}  
  2. class Paper{}  
  3.   
  4. public class DeadLockExample {  
  5.   
  6.     public static void main(String[] args)  
  7.     {  
  8.         final Pen pn =new Pen();  
  9.         final Paper pr =new Paper();  
  10.   
  11.         Thread t1 = new Thread() {  
  12.             public void run()  
  13.             {  
  14.                 synchronized(pn)  
  15.                 {  
  16.                     System.out.println("Thread1 is holding Pen");  
  17.                     try{  
  18.                         Thread.sleep(1000);  
  19.                     }  
  20.                     catch(InterruptedException e){  
  21.                         // do something  
  22.                     }  
  23.                     synchronized(pr)  
  24.                     {  
  25.                         System.out.println("Requesting for Paper");  
  26.                     }  
  27.                 }  
  28.             }  
  29.         };  
  30.         Thread t2 = new Thread() {  
  31.             public void run()  
  32.             {  
  33.                 synchronized(pr)  
  34.                 {  
  35.                     System.out.println("Thread2 is holding Paper");  
  36.                     try {  
  37.                         Thread.sleep(1000);  
  38.                     }  
  39.                     catch(InterruptedException e){  
  40.                         // do something  
  41.                     }  
  42.                     synchronized(pn)  
  43.                     {  
  44.                         System.out.println("requesting for Pen");  
  45.                     }  
  46.                 }  
  47.             }  
  48.         };  
  49.   
  50.         t1.start();  
  51.         t2.start();  
  52.     }  
  53. }  
The output of the following code generates the following output.
 
deadlockpro
 

Summary 

 
In this tutorial, we learned about Multithreading in Java and how to achieve Multithreading in our Java programs.