Multithreading is a crucial part of the Java language. If you are preparing for an upcoming interview in this domain, this post will help you to a great extent. These multithreading interview questions will help both freshers and professionals crack the job interview and grab it like a pro.
Just as the name suggests, multithreading refers to multiple threads. It is one of the most crucial Java features. Basically, multithreading is the ability of the Central Processing Unit (CPU) to execute multiple independent threads simultaneously while sharing their process resources.
The demand for a multithreading professional is rising with every passing day. Keeping its benefits in mind, newly founded and well-established companies consistently come up with multithreading vacancies.
So, if you are preparing for such a job, this post covers some of the latest multithreading interview questions for beginners and professionals. Let’s have a read ahead.
We have categorized Multithreading Interview Questions - 2024 (Updated) into 2 levels they are:
If you are a fresher and haven’t had years of working experience in this field, the below-mentioned interview questions can help you get a well-paying job with ease.
There are plenty of advantages of multithreading, such as
Do you want to enhance your skills and build your career in this Programming & Frameworks Courses domain? Then enroll for " Multithreading Training " this course will help you to achieve excellence in this domain. |
Basically, threads are the smallest and most lightweight unit of processing that a scheduler can manage independently. These threads are referred to as the process’s parts that allow efficient execution of a program with other threads or parts of the process. By using threads, you can perform complex tasks effortlessly.
Check out Multithreading in Java |
A process is a program that is under execution - also known as an active program. It is handled through the Process Control Block (PCB). On the other hand, a thread is the smallest unit of a specific process.
Here is an in-depth difference between both:
Process | Thread |
It is a program in execution that contains several threads. | It comes under a process and is a subunit’s subset. |
Under a process, the inter-process communication is expensive, complex and slower as every process has a varying address or memory space. | Under this, inter-thread communication is easy, less expensive, and quicker as threads share the same memory address. |
Processes have more overhead, are heavyweight and difficult to create. | Threads have less overhead, are lightweight and easy to create. |
They need more time for context switching, termination and creation. | They need less time for context switching, termination and creation. |
If a process is without threads, it will use more resources. | If a process that has multiple threads, it will use fewer resources. |
In Java, daemon threads are known as the service providers that offer support and services to user threads. Basically, there are two methods for daemon thread, such as isDaemon() and setDaemon(). On the contrary, user threads that have a certain lifecycle and their life are independent of other threads.
Here is an in-depth comparison between both:
Daemon Thread | User Thread |
The Java Virtual Machine (JVM) doesn’t wait for daemon threads to complete the tasks before the termination. | The Java Virtual Machine (JVM) waits for user threads to complete the tasks before the termination. |
Normally, these threads are created by JVM. | Normally, these threads are created by users to execute tasks simultaneously. |
They are not for critical tasks but supporting tasks. | They are for critical tasks and an application’s core work. |
They are known as the low priority threads; thus, they are specifically needed to support background tasks, such as releasing unused objects’ memory, garbage collection, and more. | They are high-priority tasks; thus, they are needed for running in the foreground. |
Every object has a monitor that lets the thread hold a certain lock on the object. However, the thread class doesn’t have any monitors. Usually, a thread uses the wait() method on an object to wait for the object’s monitor, which is known as the lock. And then, it uses notify() or notifyAll() methods to notify other threads that are waiting for the same lock. Thus, these three methods allow threads to communicate with each other.
The run() method is used to begin or start the same thread’s execution. When the run() method is used, no new thread gets created. The current thread executes this method. Also, the run() method can be called multiple times.
On the other hand, the start() method is used to begin or start the newly created thread’s execution. When the start() method is used, a new thread is created and it executed the task kept in the run() method. However, unlike the run() method, the start() method can also be called once.
A thread pool is a collection of worker or pre-initialized threads at the start-up that can be utilised to execute tasks and put them back in the pool upon completion. It is also known as pool threads wherein a group of threads with a fixed size is created. By decreasing the number of application threads and handling their lifecycle, you can mitigate the performance issue through a thread pool. Thus, by using threads, performance can be improved and better system stability can take place.
The join() method is used to pause the execution of a thread unless the thread is either completed or dead. This method can be generally used to stop a thread from running until some other thread gets ended. It joins the beginning of a thread execution to the end of the execution of another thread. It is regarded as the Thread class’s final method.
Basically, garbage collection is a process where the memory is managed automatically. It uses a variety of GC algorithms. Among these, Mark and Sweep is the popular one. This process comprises three varying phases, such as marking, deletion and copying/compaction. To put it simply, a garbage collector looks for objects that are not required anymore by the program. And then, it removes or deletes the programs to free up space.
Deadlock is one such situation where multiple threads get blocked forever. Generally, it occurs when multiple threads end up holding locks on varying resources and are waiting for other resources to finish their tasks.
Moving ahead, if you are a multithreading professional and have been working in this industry for quite a while now, these multithreading interview questions for experienced professionals will help you crack your next job interview.
The two ways to implement thread in Java are:
This method can be understood from the following example:
class MultithreadingDemo extends Thread
{
public void run ()
{
System.out.printIn ("My thread is in running state.");
}
public static void main (String args[])
{
MultithreadingDemoobj=new MultithreadingDemo();
obj.start();
}
}
The output of this code will be:
My thread is in running state.
This method can be understood from the following example:
class MultithreadingDemo implements Runnable
{
public void run()
{
System.out.printIn("My thread is in running state.");
}
public static void main(String args[])
{
MultithreadingDemo obj=new MultithreadingDemo();
Threadtobj =new Thread(obj); tobj.start();
}
}
The output of this code will be:
My thread is in running state.
Related Article: Java Tutorial
Synchronization is a process that allows a simple strategy to avoid the interference of thread and errors of memory consistency. This process ensures that the resource is used only by one thread at a time when a thread tries to get access to shared resources. There are three ways to achieve synchronization, such as:
When it comes to the syntax, it is:
synchronized (object)
{
//statement to be synchronized
}
If we don’t override the thread class run() method, nothing will happen. The compiler won’t display any errors. The run() method will not get executed and there will be no output with the empty implementation of the run() method.
For instance:
class MyThread extends Thread {
//don't override run() method
}
public class DontOverrideRun {
public static void main (String [] args) {
System.out.println("Started Main.");
MyThread thread1=new MyThread();
thread1.start();
System.out.println("Ended Main.");
}
}
The output will be:
Started Main.
Ended Main.
BlockingQueue represents a thread-safe queue. The producer thread puts element/resource into the queue through put() method unless it is full and the consumer thread takes the resources from the queue through take() method until it is empty. However, if a thread attempts to dequeue from an empty queue, a specific thread will get blocked until another thread has inserted an item in the queue. Or, if a thread attempts to put an item into an already full queue, a specific thread will get blocked until some threads take an item from the queue.
Here is an example of BlockingQueue:
package org.arpit.java2blog;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueuePCExample {
public static void main(String[] args) {
BlockingQueue<String> queue=new ArrayBlockingQueue<>(5);
Producer producer=new Producer(queue);
Consumer consumer=new Consumer(queue);
Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);
producerThread.start();
consumerThread.start();
}
static class Producer implements Runnable {
BlockingQueue<String> queue=null;
public Producer(BlockingQueue queue) {
super();
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println("Producing element 1");
queue.put("Element 1");
Thread.sleep(1000);
System.out.println("Producing element 2");
queue.put("Element 2");
Thread.sleep(1000);
System.out.println("Producing element 3");
queue.put("Element 3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
BlockingQueue<String> queue=null;
public Consumer(BlockingQueue queue) {
super();
this.queue = queue;
}
@Override
public void run() {
while(true)
{
try {
System.out.println("Consumed "+queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Here, the output will be:
Producing element 1
Consumed Element 1
Producing element 2
Consumed Element 2
Producing element 3
Consumed Element 3
No, we cannot start a thread twice as they only run once. In case you try to run a thread twice, it will throw a runtime exception, such as java.lang.IllegalThreadStateException.
For instance:
public class TestThreadTwice1 extends Thread{
public void run(){
System.out.printIn(" thread is executing now.........");
}
public static void main(String args[]){
TestThreadTwice1 t1 =new TestThreadTwice1();
t1.start();
t1.start();
}
}
The output of this code will be:
thread is executing now......
Exception in thread "main" java.lang.IllegalThreadStateException
A shutdown hook is a thread that gets completely invoked before JVM shuts down. It is one of the essential features of JVM as it offers the capacity for resource cleanup or saving the application before JVM shuts down. The shutdown hook can be halted by calling the halt(int) method. It can be added using the following method:
public void addShutdownHook (Thread hook) { }
Runtime r=Runtime.getRuntime ( ) ;
r.addShutdownHook (new MyThread ( ) ) ;
ThreadLocal variables are special types of variables that the Java ThreadLocal class creates and provides. Such variables cannot be read and written by the same thread. Also, two threads cannot see one another’s ThreadLocal variable. So, even if they are executing the same code, there will not be any race condition and the code will stay thread-safe.
Let’s understand more with an example:
public class ThreadLocalExp
{
public static class MyRunnable implements Runnable
{
private ThreadLocal<Integer> threadLocal =
new ThreadLocal<Integer> ( ) ;
@Override
public void run ( ) {
threadLocal.set ( (int) (Math.random ( ) * 50D) ) ;
try
{
Thread.sleep (1000) ;
} catch (InterruptedException e) {
}
System.out.println (threadLocal.get ( ) ) ;
}
}
public static void main (String [ ] args)
{
MyRunnable runnableInstance = new MyRunnable ( ) ;
Thread t1 = new Thread (runnableInstance) ;
Thread t2 = new Thread (runnableInstance) ;
// this will call run ( ) method
t1.start ( ) ;
t2.start ( ) ;
}
}
The out of this code will be:
10
33
10 33
ThreadGroup is such a class that is generally used to create multiple thread groups in a single object. This group is presented in the form of three structures wherein each thread group (except the initial thread) has its parent. Also, thread groups can comprise other thread groups as well. A thread can only access its own thread group’s information and not that of other thread groups.
With the launch of Java 5 versions, there is Thread.setUncaughtExceptionHandler(UncaughtExceptionHandler). Thus, using thread groups is no longer a necessity as it can work without the groups as well.
t1. setUncaughtExceptionHandler (new UncaughtExceptionHandler ( )
{
@Override
public void uncaughtException (Thread t, Throwable e)
{
System.out.println ("exception occurred: "+e.getMessage ( ) ) ;
}
} ;
The ExecutorService interface is a sub-interface of the Executor interface that has extra features or methods to help manage and control the execution of threads. It allows us to ensure asynchronous execution of tasks on threads.
For instance,
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent/TimeUnit;
public class TestThread {
public static void main (final String [ ] arguments ) throws InterruptedException {
ExecutorService e = Executors.newSingleThreadExecutor ( ) ;
try {
e.submit (new Thread ( ) ) ;
System.out.println ("Shutdown executor") ;
e.shutdown ( ) ;
e.awaitTermination (5, TimeUnit.SECONDS) ;
} catch (InterruptedException ex) {
System.err.println ("tasks interrupted") ;
} finally {
If ( !e.isTerminated ( ) ) {
System.err.println ("cancel non-finished tasks") ;
}
e.shutdownNow ( ) ;
System.out.println ("shutdown finished") ;
}
}
static class Task implements Runnable {
public void run ( ) {
try {
Long duration = (long) (Math.random ( ) * 20);
System.out.println ("Running Task!") ;
TimeUnit.SECONDS.sleep (duration) ;
} catch (InterruptedException ex) {
ex.printStackTrace ( ) ;
}
}
}
}
The output of this code will be:
Shutdown executor
shutdown finished
A class-level lock is known as a unique lock that every class has in Java. Such locks can be accomplished through the ‘static synchronized’ keyword and can be used to make static data thread-safe. Generally, it is used when you wish to prevent multiple threads from entering into a synchronized block.
For instance:
public class ClassLevelLockExample
{
public void classLevelLockMethod()
{
synchronized (ClassLevelLockExample.class)
{
//DO your stuff here
}
}
}
When it comes to object-level lock, it refers to the unique lock that every object has in Java. Such a lock can be accomplished through the ‘synchronized’ keyword and can be used to safeguard non-static data. Generally, it is used when you wish to synchronize a non-static method or block; thus, the thread will get to execute the code block on the instance of a class.
For instance:
public class ObjectLevelLockExample
{
public void objectLevelLockMethod()
{
synchronized (this)
{
//DO your stuff here
}
}
}
Wrapping up the article, by now, you would have understood how multithreading is a vital part of Java and modern software development. It helps in making the entire program more efficient while decreasing the use of storage resources. If you are preparing for your interview, hopefully, these multithreading interview questions will be helpful for you. Navigate through them in a better way and learn everything you can to crack the interview.
Our work-support plans provide precise options as per your project tasks. Whether you are a newbie or an experienced professional seeking assistance in completing project tasks, we are here with the following plans to meet your custom needs:
Name | Dates | |
---|---|---|
Core Java Training | Nov 23 to Dec 08 | View Details |
Core Java Training | Nov 26 to Dec 11 | View Details |
Core Java Training | Nov 30 to Dec 15 | View Details |
Core Java Training | Dec 03 to Dec 18 | View Details |
Madhuri is a Senior Content Creator at MindMajix. She has written about a range of different topics on various technologies, which include, Splunk, Tensorflow, Selenium, and CEH. She spends most of her time researching on technology, and startups. Connect with her via LinkedIn and Twitter .