Accreditation Bodies
Accreditation Bodies
Accreditation Bodies
Supercharge your career with our Multi-Cloud Engineer Bootcamp
KNOW MOREIn Java, multithreading refers to a process that runs at least two threads simultaneously to ensure maximum CPU utilization. A Java thread is a lightweight process that requires fewer resources to create and share process resources. Java multitasking uses multithreading and multiprocessing, but we recommend using multithreading instead of multiprocessing. This is because the threads use a common memory area which helps to save memory and also exchanging content between threads is a bit faster than the process. You can also use this to get an idea of multithreading interview questions C++. Apart from C++, there are many languages that support multithreading, some examples include C++, Java, Python and Go programming languages. Multithreading saves time by allowing you to perform multiple operations simultaneously. The threads are independent, so it does not prevent the user from performing multiple operations at the same time, and if an exception occurs in one thread, it does not affect the other threads. These advantages make multithreading interview questions one of the most vital parts of coding interviews in all Information Technology industry.
Filter By
Clear all
A thread is the smallest unit or task and is a lightweight sub-process executed independently. Each thread in the program runs on a different thread stack, and multiple threads form the complete program or applications. But they share common heap area.
The key benefits of Java multithreading include:
This is a frequently asked question in Multithreading interview questions.
A process is part of the main program, while threads are subsets of processes. Processes have different address spaces in the memory, while threads share the same address space/heap memory.
Expect to come across this popular question in Java thread interview questions.
Communication between synchronized threads is referred to as inter-thread communication. It is a core feature that helps to avoid thread-polling in Java. A particular thread can be paused through inter-thread communication to allow another thread to enter the block.
Some common methods that are used to perform inter-thread communication in Java are - notify(), wait() and notifyAll().
The wait() function, specified in the object class, is used to pause the current thread and wait until another thread calls the notify() function. Note that the wait() method needs to be called from a synchronized block to avoid an exception from occurring. After wait() call, current thread releases the lock and goes into wait state.
The different states in a thread life cycle include the following states:
Context switching is a feature through which the current state of a thread is saved for it to be restored and executed later. Through context switching, multiple processes can share the same CPU.
The join() method causes the current thread to stop running until the thread due to congregate with completes its task. It is a commonly used function that facilitates the execution of multiple threads in an organized manner.
A must-know for anyone heading into a Multithreading interview, this question is frequently asked in Multi threading interview questions.
The basic use of sleep() method is to pause the current thread from executing and prioritize another thread that needs to be executed before the current thread gets executed.
A program is a set of instructions. It is stored on the computer disk and is therefore inactive. When the same program is loaded into main memory and the operating system allocates a bunch of memory (application) to that program, it is called a process. Therefore, a process is an executable program. So, we can say that it is active.
When one process is loaded into main memory from secondary memory and another process is loaded from main memory into secondary memory, it is called a process switch.
Process related information is stored as a PCB (Process Control Block). Process ID, process number, process status, program counter, registers and open files are usually stored on the PCB. This PCB is stored in a protected memory area to prevent normal user access as it contains important information.
A process can spawn child processes using fork system calls. There are different types of schedulers that do different things for processes.
Let us look at the types of schedulers and how they work:
A thread is a segment or part of a process that performs some of the tasks of the process. A process can have multiple threads that can run concurrently in the process. Each thread has its own thread stack, but multiple threads in a process share a common heap for that process. Therefore, threads are lightweight and faster than processes.
Local variables are stored on the thread stack and are not shared between multiple threads and hence they are thread safe. Object fields are stored on the heap and are therefore shared across multiple threads.
An executable Java application is an example of a process. This application has some memory allocated at runtime. The application has a single thread called main which is responsible for executing our code.
Similarly, we can create multiple threads in the same application that perform different tasks.
It's no surprise that this one pops up often in multi threading interview questions.
With proactive scheduling, the highest-priority task is executed until it goes into a waiting or dead state, or a higher-priority task is created. With a time block, a task is completed at a certain time and then returns to completed tasks. The scheduler then determines which task to run next based on priority and other factors.
When changing contexts, the state of the process (or thread) is preserved so that it can be restored and execution can be resumed later from the same point. Context switching allows multiple processes to share the same CPU.
A common question in Java Multithreading interview questions, don't miss this one.
If you want to create a threaded instance, you have two options.
First Option:
We can use Thread class and write our own class extending the thread class to create thread objects.
class ExampleThread extends Thread{ public void run(){ System.out.println("Thread has started and running"); } public static void main(String args[]){ ExampleThread threadExample =new ExampleThread(); threadExample.start(); } }
Second Option:
A thread also implements Runnable, so another way to start a thread is to create an anonymous subclass, override its run() method, and then call start():
class ExampleThread implements Runnable{ public void run(){ System.out.println("thread is running..."); } public static void main(String args[]){ ExampleThread exampleThread =new ExampleThread(); Thread threadObj=new Thread(exampleThread); threadObj.start(); } }
One of the most frequently posed Multithreading questions in Java, be ready for it.
The state of a thread can be checked using the Thread.getState() method. The various states of a thread are described in the enumeration Thread. Status. They are:
This is a frequently asked question in Thread interview questions.
The Runnable interface has a single run method. It represents a computation unit that must be run in a separate thread. The Runnable interface does not allow this method to return value or to throw unchecked exceptions.
The Callable interface has a single call method and represents a task that has a value. That’s why the call method returns a value. It can also throw exceptions. Callable is generally used in ExecutorService instances to start an asynchronous task and then call the returned Future instance to get its value.
Expect to come across this popular question in Java thread interview questions.
A daemon thread is a thread that does not stop the JVM from exiting. When all non-daemon threads are finished, the JVM simply abandons any remaining daemon threads. Daemon threads are usually used to perform support or service operations for other threads, but you should note that they can be removed at any time.
If you want to start a thread as a daemon, use the setDaemon() method before the start() call.
Thread d = new Thread(() -> System.out.println("Hello from daemon!")); d.setDaemon(true); d.start();
Strangely, the message may not be printed if you run it as part of the main() method. This can happen if the main() thread terminates before the daemon has time to print the message. In general, you shouldn't do I/O on daemon threads because they can't even fill their last blocks or close resources if they're abandoned.
It's no surprise that this one pops up often in Multi threading interview questions.
wait(): As the name suggests, this is a non-static method that causes the current thread to wait and sleep until some other thread calls the notify() or notifyAll() method on the monitor (locked) object. It simply releases the lock and is mostly used for interthread communication. It is defined in the object class and should only be called from a synchronized context.
Example:
synchronized(monitor) { monitor.wait(); //Causes the current thread to wait until it is awakened, typically by being notified or interrupted. }
sleep(): As the name suggests, this is a static method that pauses or suspends the execution of the current thread for a certain period of time. It does not release the lock while waiting and is mostly used for pausing. It is defined in the thread class and does not need to be called from the synchronized context.
Example:
synchronized(monitor) { Thread.sleep(1000); //Here Lock is held by the current thread even though it is going to sleep for 1 second }
A common question in Multithreading interview questions, don't miss this one.
Class Lock: In Java, each class has a unique lock, often called a class-level lock. These locks are obtained using the "static sync" keyword and can be used to secure static data. This is typically used when you want to prevent multiple threads from accessing a synchronized block.
Example:
public class ClassLevelLockExample { public void classLevelLockMethod() { synchronized (ClassLevelLockExample.class) { //add some cool stuff here } } }
Object locking: In Java, each object has a unique lock, often called an object-level lock. These locks are accessed with the "sync" keyword and can be used to protect non-static data. This is typically used when you want to synchronize a non-static method or block so that only a thread can execute the block of code on a specific instance of the class.
Example:
public class ObjectLevelLockExample { public void objectLevelLockMethod() { synchronized (this) { //add some cool stuff here } } }
One of the most frequently posed Multi threading interview questions, be ready for it.
User and daemon are basically two types of threads that are used in Java using the "thread class".
This is a frequently asked question in Multithreading scenario based questions.
In Java, we can create a daemon thread using setDaemon(true) thread class. It is used to mark the active thread as daemon or user thread. The isDaemon() method is usually used to check whether the current thread is a daemon or not. Returns true if the thread is a daemon, otherwise, returns false.
Example:
A program that illustrates the use of the setDaemon() and isDaemon() methods.
public class DaemonThreadExample extends Thread { public DaemonThreadExample(String name){ super(name); } public void run() { if(Thread.currentThread().isDaemon()) { System.out.println(getName() + " is a daemon thread"); } else { System.out.println(getName() + " is a user thread"); } } public static void main(String[] args) { DaemonThreadExample t1 = new DaemonThreadExample ("thread1"); DaemonThreadExample t2 = new DaemonThreadExample (" thread2"); DaemonThreadExample t3 = new DaemonThreadExample (" thread3"); t1.setDaemon(true); t1.start(); t2.start(); t3.setDaemon(true); t3.start(); } }
Output:
thread1 is a daemon thread
thread3 is a daemon thread
thread2 is a user thread
But the setDaemon() method can only be called before the start() method, otherwise it will definitely throw an IllegalThreadStateException as shown below:
public class DaemonThread extends Thread { public void run() { System.out.println("Thread name: " + Thread.currentThread().getName()); System.out.println("Check if its DaemonThread: " + Thread.currentThread().isDaemon()); } public static void main(String[] args) { DaemonThread t1 = new DaemonThread(); DaemonThread t2 = new DaemonThread(); t1.start(); // Exception as the thread is already started on next line t1.setDaemon(true); t2.start(); } }
Output:
Thread name: Thread-0
Check if its DaemonThread: false
A volatile variable is basically a keyword used to provide visibility and handling of variable changes in multi-threaded programming. This keyword cannot be used with classes and methods, but it can be used with variables. It is simply used to achieve thread safety for variables. When you mark a variable as volatile, all threads can read its value directly from main memory instead of the CPU cache, so each thread gets the updated value of the variable.
Threads can communicate using three methods i.e., wait(), notify(), and notifyAll().
Expect to come across this popular question in Multithreading interview questions.
Yes, it is possible. If both threads acquire locks on different objects, then they can execute concurrently without any problem.
The finalize() method is basically a method of the Object class that is specifically used to clean up unmanaged resources immediately before garbage collection. It is by no means intended to be called a normal method. After the finalize() method completes, the object is automatically destroyed.
It's no surprise that this one pops up often in Java multithreading interview questions.
No, it's not possible at all. You need to call the start method to create a new thread otherwise run method won't create a new thread. Instead, it will execute in the current thread.
This question is a regular feature in Java thread interview questions, be ready to tackle it.
Of course, it is possible. In multithreaded programming, each thread maintains its own separate stack area in memory because of which every thread is independent of each other rather than dependent.
The wait() method needs to be called from a synchronized method or non-static block as wait() is an object method and not a class method. Basically it is defined in object class as an object’s behavior.
Main
start() method internally invokes the overridden run() method.
A process where two or more actions / tasks of the same process run concurrently.
start()
Integer is return type of thread priority.
The termination flag or termination status is an internal thread flag that is set when a thread is terminated. Set this up by calling thread.interrupt() on the thread object.
If a thread is currently suspended within a method that throws an exception (wait, join, sleep, etc.), that method immediately throws a Canceled exception. A thread is free to handle this exception according to its own logic.
If there is no thread in such a method and thread.interrupt() is called, nothing special happens. The thread is responsible for periodically checking the interrupt state using the static Thread.interrupted() method or the isInterrupted() instance. The difference between these methods is that static Thread.interrupted() clears the interrupt flag, while isInterrupted() does not.
This is a frequently asked question in Java thread interview questions.
Executor and ExecutorService are two related interfaces of the java.util.concurrent framework. A launcher is a very simple interface with a single execution method that accepts executable instances for execution. In most cases, this is the interface that your task execution code should depend on.
ExecutorService extends the Executor interface with multiple concurrent task execution service handling and lifecycle control methods (task termination on termination) and more sophisticated asynchronous task processing methods, including Futures.
Expect to come across this popular question in Multithreading questions in Java.
The ExecutorService interface has three standard implementations:
One of the most frequently posed Java thread interview questions, be ready for it.
The Java memory model is part of the Java language definition described in Chapter 17. It determines how several threads use shared memory in a concurrent Java application and how data changes made by one thread are visible to other threads. Although JMM is quite short and concise, it can be difficult to understand without a strong mathematical background.
The need for a memory model is because the way your Java code accesses data doesn't happen at lower levels. The Java compiler, the JIT compiler, and even the CPU can rearrange or optimize memory writes and reads as long as the observable result of those reads and writes is the same.
A volatile field has special properties according to the Java memory model. Reading and writing a mutable variable are synchronous operations, which means that they have perfect ordering (all threads follow the same order of those operations).
Reading a constant variable will definitely track the last write to that variable in that order. If you have a field that is accessed by multiple threads and written to at least one thread, you should consider making it mutable, otherwise there is little guarantee that a particular thread will read from that field.
Another guarantee of volatility is the atomicity of writing and reading 6 -bit values (long and double). Without a volatile modifier, reading such a field may detect a value partially written by another thread.
Writing to an int (32-bit) variable is guaranteed to be atomic, mutable or not. A long (6 -bit) variable can be written in two separate steps, for example on 32-bit architectures, so there is no guarantee of atomicity by default. However, if you specify a volatile modifier, access to the long variable is guaranteed on an atomic basis.
The increment operation is usually done in several steps (getting the value, changing it, and writing it back), so it is never guaranteed to be atomic, regardless of whether the variable is mutable or not. If you want to implement atomic addition of a value, you should use classes AtomicInteger, AtomicLong, etc.
A staple in Multithreading questions, be prepared to answer this one.
The synchronized keyword before a block means that any thread entering this block has to acquire the monitor (the object in brackets). If the monitor is already acquired by another thread, the former thread will enter the BLOCKED state and wait until the monitor is released.
synchronized(object) { // ... }");
A synchronized instance method has the same semantics, but the instance itself acts as a monitor.
synchronized void instanceMethod() { // ... }");
For a static synchronized method, the monitor is the Class object representing the declaring class.
static synchronized void staticMethod() { // ... }");
If a method is an instance method, the instance acts as a method monitor. Two threads that call the method on different occasions get different screens so that neither of them blocks.
If the method is static, the monitor is an object of the class. Both threads have the same monitor, so one of them will probably block and wait for the other to exit the synchronized method.
A thread that owns an object's monitor (for example, a thread that has entered a synchronized section protected by the object) can call object.wait() to temporarily release the monitor and allow other threads to acquire the monitor.
This can be done, for example, to wait for a certain condition. If another thread that acquired the monitor meets the condition, it can call object.notify() or object.notifyAll() and release the monitor. The notify method wakes up one thread in the waiting state, and the notifyAll method wakes up all the threads waiting for that monitor, all of which compete to regain the lock.
It's no surprise that this one pops up often in Multi threading interview questions.
A deadlock is a state in a thread pool that cannot progress because each thread in the pool must acquire a resource that another thread in the pool has already acquired. The simplest case is when two threads each need to lock two resources to progress, the first resource is already locked by one thread, and the second is already locked by the other thread. These threads never lock either resource and, therefore, never progress.
Livelock is a case where multiple threads respond to conditions or events of their own making. An event occurs in one thread and must be processed in another thread. During this processing, a new event occurs, which must be processed in the first thread, and so on. Such threads live and do not block but still do not progress because they burden each other with unnecessary work.
Starvation is when a thread cannot obtain a resource because another thread (or threads) is using it for too long or has a higher priority. The thread cannot progress and thus cannot do any useful work.
A common question in Java thread interview questions, don't miss this one.
The Fork/Join framework allows recursive algorithms to be parallelized. The main problem with a recursively parallel ThreadPoolExecutor is that it can quickly run out of threads because each recursive step requires its own thread while the threads on the stack are idle and waiting.
The starting point of the Fork/join framework is the ForkJoinPool class, which is an implementation of ExecutorService. It implements a job reservation algorithm where idle threads try to "steal" work from busy threads. This allows computation to be spread across different threads and progress using fewer threads than a normal thread pool would require.
We know that every object has a monitor that allows a thread to hold a lock on the object. But thread class does not contain monitors. A thread usually waits for control of an object (a lock) by calling the wait method of the object, and notifies other threads waiting on the same lock using the notify() or notifyAll() method. Therefore, these three methods are only called on objects and allow all threads to communicate with each thread created for that object.
One of the most frequently posed Java Multithreading interview questions, be ready for it.
The Problems With Synchronized Keyword:
The Solution: Reentrant Lock:
Java provides a better way to deal with the above problems that handle synchronization.
Now let us see how we can use this mechanism:
public void methodName(){ bufferLock.lock(); try { //sharedResource } catch(Exception e) { e.printStackTrace(); } finally { bufferLock.unlock(); } }
In the above code snippet, you can notice that the thread must be locked before the shared resource can be executed. And after executing the try block, the thread finally releases the block lock using the unlock() method. Note that regardless of whether an exception occurs or not, the finally block is always executed.
When we use a Java application, the operating system allocates some memory to that application to store and run the program. This application is called a process when it is running. Now there can be multiple threads in the same application and each thread can perform different tasks like IO, DB operations etc.
All threads of the same process (application) share the mass memory of that process. On the other hand, each thread in this application has its own memory called thread stack and stores local variables in it.
Note that when we create an object of a class, that object is stored on the heap, not the thread stack. The thread stack is private memory reserved for each thread, which only stores local variable
This question is a regular feature in Java thread interview questions, be ready to tackle it.
Thread stack and heap:
First, the Java Virtual Machine divides its memory into stack and heap memories.
It stores all objects on the heap and stack local primitives and local object references.
Most importantly, each thread, including the main thread, has its own private stack. Local primitives and local reference variables are stored on this stack (essentially the thread stack).
Therefore one thread does not share its local variables with any other thread because these local variables and references are on the thread's private stack. Therefore, local variables are always thread-safe.
Let us give a simple example to understand this:
Thread-Safety for local variables:
public class ThreadExample implements Runnable{ public Integer counter; @Override public void run() { counter = new Random().nextInt(); Integer count = new Random().nextInt(); System.out.println("counter : "+counter+" count : "+count); } public static void main(String[] args) { ThreadExample threadExample = new ThreadExample(); Thread thread1 = new Thread(threadExample); Thread thread2 = new Thread(threadExample); thread1.start(); thread2.start(); } }
The output of the above program:
counter : -2066897874 count : 1775146445 counter : 170327989 count : -1649657772
In the example above, a ThreadExample instance is created on line 11, and two Thread objects are created on the next two lines (12 and 13), starting on lines 1 and 15. These threads execute the execute method of the same instance “threadExample”.
When these two threads execute the execute method, they create their own copy of the local count variable on their private stack. Because those stacks are private, no two threads can share the same copy of the count variable. That's why it is thread-safe. Also, the counter variable is assigned a random integer, so it probably won't assign the same integer to the count variable.
But both threads refer to the same instance ‘threadExample’ of ThreadExample class. This instance is on the heap and hence its field the counter is also on the heap. So there is only one copy of the field counter on the heap which is shared between these two threads. And hence there is a chance of collision between the threads which can lead to a race condition. That’s why the counter field is not thread-safe.
This is a frequently asked question in Multi threading interview questions.
A thread pool is simply a set of worker threads, pre-initialized at startup, that can be used to perform tasks and return to the pool when they are finished. This is called pool threads, where a pool of threads of fixed size is created.
By reducing the number of threads in an application and managing their life cycle, the performance problem can be mitigated by thread pooling. Using threads can improve performance and improve system stability. The java.util.concurrent.Executors class typically provides factory methods for creating thread pools.
The join() method is usually used to pause the execution of the current thread unless the specified thread on which the join is called is dead or completed. This method can be used to block a thread until another thread finishes. It connects the beginning of the execution of a thread to the end of the execution of another thread. This is considered the last method of the thread class.
Garbage collection is basically a process of managing memory automatically. It uses several GC algorithms among which the popular one includes Mark and Sweep. The process includes three phases i.e., marking, deletion, and compaction/copying. In simple words, a garbage collector finds objects that are no longer required by the program and then delete or remove these unused objects to free up the memory space.
Expect to come across this popular question in Multithreading questions.
The Lock interface was introduced in Java 1.5 and is generally used as a synchronization mechanism to provide important locking functionality.
Advantages of using the Lock interface compared to the sync block:
A deadlock is a situation where each thread is waiting for resources held by other waiting threads. This situation causes the thread to fail to start, which causes the program to pause and break the code at runtime.
It's no surprise that this one pops up often in Java Thread interview questions.
A Deadlock situation can be detected by running the executable code on cmd and subsequently collecting the thread dump. If a deadlock situation is present, the cmd will throw up a message.
This is one of the most common Java Multithreading interview questions asked in technical interviews.
Deadlock situations in Java can be avoided by:
By way of avoiding nested thread locks and providing locks to only one thread at a time can help in reducing the risk of deadlock occurrence.
By using thread join – this function helps the thread to wait for other threads to execute before its own execution, thereby preventing multiple threads from waiting for resources used by other threads.
Individual threads do have their stacks in multithreaded programming. Each thread is independent of the other and maintains its own stack in the memory.
Thready safety can be achieved if multiple threads can use a particular class function without the occurrence of the race condition. In Multithreaded programming, thread safety can be achieved by:
Atomic operations are performed in a single task unit without interfering with other operations. In multi-threaded environments, atomic operations are required to avoid data inconsistencies. int is not an atomic operation. So, when one thread reads this value and increments it by one, the other thread reads the original value, resulting in an incorrect result.
To solve this problem, we need to make sure that the number of sum operations is atomic. We can do this using synchronization, but java.util.concurrent.atomic in Java 5 provides wrapper classes for int and long that can be used to achieve this. atomically without synchronization.
In synchronization, we don’t know how much time a thread will get a chance after a previous thread has released the lock. This can lead to the problem of starvation whereas, in the case of the lock, we have its implementing class reentrant lock which has one of its constructors which lets you pass fairness property as one of its arguments that let the longest waiting thread get the chance to acquire the lock.
In synchronization, if a thread is waiting for another thread, then the waiting thread won’t do any other activity which doesn’t require lock access but with the lock interface, there is a trylock() method with which you can try to access the lock and if you don’t get the lock you can perform other alternate tasks. This helps to improve the performance of the application.
There is no API to check how many threads are waiting for a particular lock whereas this is possible with lock interface implementation class ReentrantLock methods.
Using the lock interface One can get better control of locks, with the methods such as holdCount() method which is not found with synchronization.
One of the most frequently posed Thread interview questions, be ready for it.
Java 5 introduced the Executor framework with the java.util.concurrent. Executor interface. The Executor Framework is a framework for standardizing the invocation, scheduling, execution and management of asynchronous tasks according to execution conventions. Creating many threads without a maximum limit can cause the application to run out of memory and hence the application will crash.
So creating a ThreadPool is a better solution because a limited number of threads can be pooled and reused once they are put again in the thread pool. The Executor framework makes it easy to create thread pools in java for multi-threading applications.
This is a frequently asked question in Java Multithreading interview questions for experienced.
Actually, Java 5 introduced java.util.concurrent.Callable interface in concurrency package that is similar to Runnable interface but can return any Object and throw Exception. The Callable interface uses java generics to define the return type of the Object. Executors class provides useful methods to execute Callable in a thread pool.
Since callable tasks run parallel, we have to wait for the returned Object. Callable tasks return java.util.concurrent.Future object. Using Future we can find out the status of the Callable task and get the returned Object. It provides the get() method that can wait for the Callable to finish and then return the result.
Thread or process context switching is basically an important feature of multithreading. It is referred to as switching of CPU from one thread or process to another one. It allows multiple processes to share the same CPU cores. In context switching, the state of thread or process is stored on PCB or TCB, so that the execution of the thread can be resumed later if required.
FutureTask is the base implementation class of the Future interface and we can use it with Executors for asynchronous processing. Most of the time we don't need to use FutureTask class but it comes really handy if we want to override some of the methods of the Future interface and want to keep most of the base implementation. We can just extend this class and override the methods according to our requirements.
Expect to come across this popular question in Java multithreading questions.
BlockingQueue is typically used for one thread to create objects to be consumed by another thread. Here is a diagram that illustrates this principle:
The "producing thread" continues to create new objects and add them to the BlockingQueue until the queue reaches some upper limit. It's a limit, in other words. When the blocking queue reaches its upper limit, the creating thread is blocked from adding a new object. It remains blocked until the consuming thread lives the object.
"Consumer thread" removes objects from the block queue to process them. If a consuming thread tries to remove an object from an empty queue, the consuming thread is blocked until the producing thread enqueues the object.
CyclicBarrier and CountDownLatch, both required to handle multi-threaded programming. But there are differences between them as shown below:
It's no surprise that this one pops up often in Multithreading interview questions.
The Executors class provides helper methods for the Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes. The Executors class can be used to easily create a thread pool in Java and is also the only class that supports running Callable applications.
Some important concurrent API enhancements are:
Interthread communication, as the name suggests, is a process or mechanism that allows multiple threads to communicate with each other. It is specifically used in Java to prevent thread polling and can be obtained by the wait(), notify() and notifyAll() methods.
ConcurrentHashMap also provides non-locking numbers, unlike Hashtable. Therefore, ConcurrentHashMap is considered faster than Hashtable, especially when the number of readers is more than the number of writers.
Expect to come across this popular question in Java Multithreading interview questions for experienced.
A semaphore is considered a thread synchronization construct that is typically needed to control and manage access to a shared resource using counters. It just sets the thread limit. The semaphore class is defined in the java.util.concurrent package and can be used to send signals between threads to prevent missing signals or to protect critical parts. It can also be used to implement resources or a limited pool.
So nothing happens unless we override the run() method. The compiler does not show an error. This calls the run() method of the thread class and we just don't get the result because the run() method has an empty implementation.
Example:
class ThreadExample extends Thread { //don't override run() method } public class DontOverrideRun { public static void main(String[] args) { System.out.println("Main thread has started"); ThreadExample thread1=new ThreadExample (); thread1.start(); System.out.println("Main thread has completed"); } }
Output:
Main thread has started Main thread has completed
Multithreading is a concept that appears in many programming languages. Although multithreaded languages can run on a single thread, multithreading cannot be disabled in languages that do not support this feature. C, JAVA, C# etc. are languages that support multithreading. JavaScript is a single-threaded language.
A thread is the smallest unit or task and is a lightweight sub-process executed independently. Each thread in the program runs on a different thread stack, and multiple threads form the complete program or applications. But they share common heap area.
The key benefits of Java multithreading include:
This is a frequently asked question in Multithreading interview questions.
A process is part of the main program, while threads are subsets of processes. Processes have different address spaces in the memory, while threads share the same address space/heap memory.
Expect to come across this popular question in Java thread interview questions.
Communication between synchronized threads is referred to as inter-thread communication. It is a core feature that helps to avoid thread-polling in Java. A particular thread can be paused through inter-thread communication to allow another thread to enter the block.
Some common methods that are used to perform inter-thread communication in Java are - notify(), wait() and notifyAll().
The wait() function, specified in the object class, is used to pause the current thread and wait until another thread calls the notify() function. Note that the wait() method needs to be called from a synchronized block to avoid an exception from occurring. After wait() call, current thread releases the lock and goes into wait state.
The different states in a thread life cycle include the following states:
Context switching is a feature through which the current state of a thread is saved for it to be restored and executed later. Through context switching, multiple processes can share the same CPU.
The join() method causes the current thread to stop running until the thread due to congregate with completes its task. It is a commonly used function that facilitates the execution of multiple threads in an organized manner.
A must-know for anyone heading into a Multithreading interview, this question is frequently asked in Multi threading interview questions.
The basic use of sleep() method is to pause the current thread from executing and prioritize another thread that needs to be executed before the current thread gets executed.
A program is a set of instructions. It is stored on the computer disk and is therefore inactive. When the same program is loaded into main memory and the operating system allocates a bunch of memory (application) to that program, it is called a process. Therefore, a process is an executable program. So, we can say that it is active.
When one process is loaded into main memory from secondary memory and another process is loaded from main memory into secondary memory, it is called a process switch.
Process related information is stored as a PCB (Process Control Block). Process ID, process number, process status, program counter, registers and open files are usually stored on the PCB. This PCB is stored in a protected memory area to prevent normal user access as it contains important information.
A process can spawn child processes using fork system calls. There are different types of schedulers that do different things for processes.
Let us look at the types of schedulers and how they work:
A thread is a segment or part of a process that performs some of the tasks of the process. A process can have multiple threads that can run concurrently in the process. Each thread has its own thread stack, but multiple threads in a process share a common heap for that process. Therefore, threads are lightweight and faster than processes.
Local variables are stored on the thread stack and are not shared between multiple threads and hence they are thread safe. Object fields are stored on the heap and are therefore shared across multiple threads.
An executable Java application is an example of a process. This application has some memory allocated at runtime. The application has a single thread called main which is responsible for executing our code.
Similarly, we can create multiple threads in the same application that perform different tasks.
It's no surprise that this one pops up often in multi threading interview questions.
With proactive scheduling, the highest-priority task is executed until it goes into a waiting or dead state, or a higher-priority task is created. With a time block, a task is completed at a certain time and then returns to completed tasks. The scheduler then determines which task to run next based on priority and other factors.
When changing contexts, the state of the process (or thread) is preserved so that it can be restored and execution can be resumed later from the same point. Context switching allows multiple processes to share the same CPU.
A common question in Java Multithreading interview questions, don't miss this one.
If you want to create a threaded instance, you have two options.
First Option:
We can use Thread class and write our own class extending the thread class to create thread objects.
class ExampleThread extends Thread{ public void run(){ System.out.println("Thread has started and running"); } public static void main(String args[]){ ExampleThread threadExample =new ExampleThread(); threadExample.start(); } }
Second Option:
A thread also implements Runnable, so another way to start a thread is to create an anonymous subclass, override its run() method, and then call start():
class ExampleThread implements Runnable{ public void run(){ System.out.println("thread is running..."); } public static void main(String args[]){ ExampleThread exampleThread =new ExampleThread(); Thread threadObj=new Thread(exampleThread); threadObj.start(); } }
One of the most frequently posed Multithreading questions in Java, be ready for it.
The state of a thread can be checked using the Thread.getState() method. The various states of a thread are described in the enumeration Thread. Status. They are:
This is a frequently asked question in Thread interview questions.
The Runnable interface has a single run method. It represents a computation unit that must be run in a separate thread. The Runnable interface does not allow this method to return value or to throw unchecked exceptions.
The Callable interface has a single call method and represents a task that has a value. That’s why the call method returns a value. It can also throw exceptions. Callable is generally used in ExecutorService instances to start an asynchronous task and then call the returned Future instance to get its value.
Expect to come across this popular question in Java thread interview questions.
A daemon thread is a thread that does not stop the JVM from exiting. When all non-daemon threads are finished, the JVM simply abandons any remaining daemon threads. Daemon threads are usually used to perform support or service operations for other threads, but you should note that they can be removed at any time.
If you want to start a thread as a daemon, use the setDaemon() method before the start() call.
Thread d = new Thread(() -> System.out.println("Hello from daemon!")); d.setDaemon(true); d.start();
Strangely, the message may not be printed if you run it as part of the main() method. This can happen if the main() thread terminates before the daemon has time to print the message. In general, you shouldn't do I/O on daemon threads because they can't even fill their last blocks or close resources if they're abandoned.
It's no surprise that this one pops up often in Multi threading interview questions.
wait(): As the name suggests, this is a non-static method that causes the current thread to wait and sleep until some other thread calls the notify() or notifyAll() method on the monitor (locked) object. It simply releases the lock and is mostly used for interthread communication. It is defined in the object class and should only be called from a synchronized context.
Example:
synchronized(monitor) { monitor.wait(); //Causes the current thread to wait until it is awakened, typically by being notified or interrupted. }
sleep(): As the name suggests, this is a static method that pauses or suspends the execution of the current thread for a certain period of time. It does not release the lock while waiting and is mostly used for pausing. It is defined in the thread class and does not need to be called from the synchronized context.
Example:
synchronized(monitor) { Thread.sleep(1000); //Here Lock is held by the current thread even though it is going to sleep for 1 second }
A common question in Multithreading interview questions, don't miss this one.
Class Lock: In Java, each class has a unique lock, often called a class-level lock. These locks are obtained using the "static sync" keyword and can be used to secure static data. This is typically used when you want to prevent multiple threads from accessing a synchronized block.
Example:
public class ClassLevelLockExample { public void classLevelLockMethod() { synchronized (ClassLevelLockExample.class) { //add some cool stuff here } } }
Object locking: In Java, each object has a unique lock, often called an object-level lock. These locks are accessed with the "sync" keyword and can be used to protect non-static data. This is typically used when you want to synchronize a non-static method or block so that only a thread can execute the block of code on a specific instance of the class.
Example:
public class ObjectLevelLockExample { public void objectLevelLockMethod() { synchronized (this) { //add some cool stuff here } } }
One of the most frequently posed Multi threading interview questions, be ready for it.
User and daemon are basically two types of threads that are used in Java using the "thread class".
This is a frequently asked question in Multithreading scenario based questions.
In Java, we can create a daemon thread using setDaemon(true) thread class. It is used to mark the active thread as daemon or user thread. The isDaemon() method is usually used to check whether the current thread is a daemon or not. Returns true if the thread is a daemon, otherwise, returns false.
Example:
A program that illustrates the use of the setDaemon() and isDaemon() methods.
public class DaemonThreadExample extends Thread { public DaemonThreadExample(String name){ super(name); } public void run() { if(Thread.currentThread().isDaemon()) { System.out.println(getName() + " is a daemon thread"); } else { System.out.println(getName() + " is a user thread"); } } public static void main(String[] args) { DaemonThreadExample t1 = new DaemonThreadExample ("thread1"); DaemonThreadExample t2 = new DaemonThreadExample (" thread2"); DaemonThreadExample t3 = new DaemonThreadExample (" thread3"); t1.setDaemon(true); t1.start(); t2.start(); t3.setDaemon(true); t3.start(); } }
Output:
thread1 is a daemon thread
thread3 is a daemon thread
thread2 is a user thread
But the setDaemon() method can only be called before the start() method, otherwise it will definitely throw an IllegalThreadStateException as shown below:
public class DaemonThread extends Thread { public void run() { System.out.println("Thread name: " + Thread.currentThread().getName()); System.out.println("Check if its DaemonThread: " + Thread.currentThread().isDaemon()); } public static void main(String[] args) { DaemonThread t1 = new DaemonThread(); DaemonThread t2 = new DaemonThread(); t1.start(); // Exception as the thread is already started on next line t1.setDaemon(true); t2.start(); } }
Output:
Thread name: Thread-0
Check if its DaemonThread: false
A volatile variable is basically a keyword used to provide visibility and handling of variable changes in multi-threaded programming. This keyword cannot be used with classes and methods, but it can be used with variables. It is simply used to achieve thread safety for variables. When you mark a variable as volatile, all threads can read its value directly from main memory instead of the CPU cache, so each thread gets the updated value of the variable.
Threads can communicate using three methods i.e., wait(), notify(), and notifyAll().
Expect to come across this popular question in Multithreading interview questions.
Yes, it is possible. If both threads acquire locks on different objects, then they can execute concurrently without any problem.
The finalize() method is basically a method of the Object class that is specifically used to clean up unmanaged resources immediately before garbage collection. It is by no means intended to be called a normal method. After the finalize() method completes, the object is automatically destroyed.
It's no surprise that this one pops up often in Java multithreading interview questions.
No, it's not possible at all. You need to call the start method to create a new thread otherwise run method won't create a new thread. Instead, it will execute in the current thread.
This question is a regular feature in Java thread interview questions, be ready to tackle it.
Of course, it is possible. In multithreaded programming, each thread maintains its own separate stack area in memory because of which every thread is independent of each other rather than dependent.
The wait() method needs to be called from a synchronized method or non-static block as wait() is an object method and not a class method. Basically it is defined in object class as an object’s behavior.
Main
start() method internally invokes the overridden run() method.
A process where two or more actions / tasks of the same process run concurrently.
start()
Integer is return type of thread priority.
The termination flag or termination status is an internal thread flag that is set when a thread is terminated. Set this up by calling thread.interrupt() on the thread object.
If a thread is currently suspended within a method that throws an exception (wait, join, sleep, etc.), that method immediately throws a Canceled exception. A thread is free to handle this exception according to its own logic.
If there is no thread in such a method and thread.interrupt() is called, nothing special happens. The thread is responsible for periodically checking the interrupt state using the static Thread.interrupted() method or the isInterrupted() instance. The difference between these methods is that static Thread.interrupted() clears the interrupt flag, while isInterrupted() does not.
This is a frequently asked question in Java thread interview questions.
Executor and ExecutorService are two related interfaces of the java.util.concurrent framework. A launcher is a very simple interface with a single execution method that accepts executable instances for execution. In most cases, this is the interface that your task execution code should depend on.
ExecutorService extends the Executor interface with multiple concurrent task execution service handling and lifecycle control methods (task termination on termination) and more sophisticated asynchronous task processing methods, including Futures.
Expect to come across this popular question in Multithreading questions in Java.
The ExecutorService interface has three standard implementations:
One of the most frequently posed Java thread interview questions, be ready for it.
The Java memory model is part of the Java language definition described in Chapter 17. It determines how several threads use shared memory in a concurrent Java application and how data changes made by one thread are visible to other threads. Although JMM is quite short and concise, it can be difficult to understand without a strong mathematical background.
The need for a memory model is because the way your Java code accesses data doesn't happen at lower levels. The Java compiler, the JIT compiler, and even the CPU can rearrange or optimize memory writes and reads as long as the observable result of those reads and writes is the same.
A volatile field has special properties according to the Java memory model. Reading and writing a mutable variable are synchronous operations, which means that they have perfect ordering (all threads follow the same order of those operations).
Reading a constant variable will definitely track the last write to that variable in that order. If you have a field that is accessed by multiple threads and written to at least one thread, you should consider making it mutable, otherwise there is little guarantee that a particular thread will read from that field.
Another guarantee of volatility is the atomicity of writing and reading 6 -bit values (long and double). Without a volatile modifier, reading such a field may detect a value partially written by another thread.
Writing to an int (32-bit) variable is guaranteed to be atomic, mutable or not. A long (6 -bit) variable can be written in two separate steps, for example on 32-bit architectures, so there is no guarantee of atomicity by default. However, if you specify a volatile modifier, access to the long variable is guaranteed on an atomic basis.
The increment operation is usually done in several steps (getting the value, changing it, and writing it back), so it is never guaranteed to be atomic, regardless of whether the variable is mutable or not. If you want to implement atomic addition of a value, you should use classes AtomicInteger, AtomicLong, etc.
A staple in Multithreading questions, be prepared to answer this one.
The synchronized keyword before a block means that any thread entering this block has to acquire the monitor (the object in brackets). If the monitor is already acquired by another thread, the former thread will enter the BLOCKED state and wait until the monitor is released.
synchronized(object) { // ... }");
A synchronized instance method has the same semantics, but the instance itself acts as a monitor.
synchronized void instanceMethod() { // ... }");
For a static synchronized method, the monitor is the Class object representing the declaring class.
static synchronized void staticMethod() { // ... }");
If a method is an instance method, the instance acts as a method monitor. Two threads that call the method on different occasions get different screens so that neither of them blocks.
If the method is static, the monitor is an object of the class. Both threads have the same monitor, so one of them will probably block and wait for the other to exit the synchronized method.
A thread that owns an object's monitor (for example, a thread that has entered a synchronized section protected by the object) can call object.wait() to temporarily release the monitor and allow other threads to acquire the monitor.
This can be done, for example, to wait for a certain condition. If another thread that acquired the monitor meets the condition, it can call object.notify() or object.notifyAll() and release the monitor. The notify method wakes up one thread in the waiting state, and the notifyAll method wakes up all the threads waiting for that monitor, all of which compete to regain the lock.
It's no surprise that this one pops up often in Multi threading interview questions.
A deadlock is a state in a thread pool that cannot progress because each thread in the pool must acquire a resource that another thread in the pool has already acquired. The simplest case is when two threads each need to lock two resources to progress, the first resource is already locked by one thread, and the second is already locked by the other thread. These threads never lock either resource and, therefore, never progress.
Livelock is a case where multiple threads respond to conditions or events of their own making. An event occurs in one thread and must be processed in another thread. During this processing, a new event occurs, which must be processed in the first thread, and so on. Such threads live and do not block but still do not progress because they burden each other with unnecessary work.
Starvation is when a thread cannot obtain a resource because another thread (or threads) is using it for too long or has a higher priority. The thread cannot progress and thus cannot do any useful work.
A common question in Java thread interview questions, don't miss this one.
The Fork/Join framework allows recursive algorithms to be parallelized. The main problem with a recursively parallel ThreadPoolExecutor is that it can quickly run out of threads because each recursive step requires its own thread while the threads on the stack are idle and waiting.
The starting point of the Fork/join framework is the ForkJoinPool class, which is an implementation of ExecutorService. It implements a job reservation algorithm where idle threads try to "steal" work from busy threads. This allows computation to be spread across different threads and progress using fewer threads than a normal thread pool would require.
We know that every object has a monitor that allows a thread to hold a lock on the object. But thread class does not contain monitors. A thread usually waits for control of an object (a lock) by calling the wait method of the object, and notifies other threads waiting on the same lock using the notify() or notifyAll() method. Therefore, these three methods are only called on objects and allow all threads to communicate with each thread created for that object.
One of the most frequently posed Java Multithreading interview questions, be ready for it.
The Problems With Synchronized Keyword:
The Solution: Reentrant Lock:
Java provides a better way to deal with the above problems that handle synchronization.
Now let us see how we can use this mechanism:
public void methodName(){ bufferLock.lock(); try { //sharedResource } catch(Exception e) { e.printStackTrace(); } finally { bufferLock.unlock(); } }
In the above code snippet, you can notice that the thread must be locked before the shared resource can be executed. And after executing the try block, the thread finally releases the block lock using the unlock() method. Note that regardless of whether an exception occurs or not, the finally block is always executed.
When we use a Java application, the operating system allocates some memory to that application to store and run the program. This application is called a process when it is running. Now there can be multiple threads in the same application and each thread can perform different tasks like IO, DB operations etc.
All threads of the same process (application) share the mass memory of that process. On the other hand, each thread in this application has its own memory called thread stack and stores local variables in it.
Note that when we create an object of a class, that object is stored on the heap, not the thread stack. The thread stack is private memory reserved for each thread, which only stores local variable
This question is a regular feature in Java thread interview questions, be ready to tackle it.
Thread stack and heap:
First, the Java Virtual Machine divides its memory into stack and heap memories.
It stores all objects on the heap and stack local primitives and local object references.
Most importantly, each thread, including the main thread, has its own private stack. Local primitives and local reference variables are stored on this stack (essentially the thread stack).
Therefore one thread does not share its local variables with any other thread because these local variables and references are on the thread's private stack. Therefore, local variables are always thread-safe.
Let us give a simple example to understand this:
Thread-Safety for local variables:
public class ThreadExample implements Runnable{ public Integer counter; @Override public void run() { counter = new Random().nextInt(); Integer count = new Random().nextInt(); System.out.println("counter : "+counter+" count : "+count); } public static void main(String[] args) { ThreadExample threadExample = new ThreadExample(); Thread thread1 = new Thread(threadExample); Thread thread2 = new Thread(threadExample); thread1.start(); thread2.start(); } }
The output of the above program:
counter : -2066897874 count : 1775146445 counter : 170327989 count : -1649657772
In the example above, a ThreadExample instance is created on line 11, and two Thread objects are created on the next two lines (12 and 13), starting on lines 1 and 15. These threads execute the execute method of the same instance “threadExample”.
When these two threads execute the execute method, they create their own copy of the local count variable on their private stack. Because those stacks are private, no two threads can share the same copy of the count variable. That's why it is thread-safe. Also, the counter variable is assigned a random integer, so it probably won't assign the same integer to the count variable.
But both threads refer to the same instance ‘threadExample’ of ThreadExample class. This instance is on the heap and hence its field the counter is also on the heap. So there is only one copy of the field counter on the heap which is shared between these two threads. And hence there is a chance of collision between the threads which can lead to a race condition. That’s why the counter field is not thread-safe.
This is a frequently asked question in Multi threading interview questions.
A thread pool is simply a set of worker threads, pre-initialized at startup, that can be used to perform tasks and return to the pool when they are finished. This is called pool threads, where a pool of threads of fixed size is created.
By reducing the number of threads in an application and managing their life cycle, the performance problem can be mitigated by thread pooling. Using threads can improve performance and improve system stability. The java.util.concurrent.Executors class typically provides factory methods for creating thread pools.
The join() method is usually used to pause the execution of the current thread unless the specified thread on which the join is called is dead or completed. This method can be used to block a thread until another thread finishes. It connects the beginning of the execution of a thread to the end of the execution of another thread. This is considered the last method of the thread class.
Garbage collection is basically a process of managing memory automatically. It uses several GC algorithms among which the popular one includes Mark and Sweep. The process includes three phases i.e., marking, deletion, and compaction/copying. In simple words, a garbage collector finds objects that are no longer required by the program and then delete or remove these unused objects to free up the memory space.
Expect to come across this popular question in Multithreading questions.
The Lock interface was introduced in Java 1.5 and is generally used as a synchronization mechanism to provide important locking functionality.
Advantages of using the Lock interface compared to the sync block:
A deadlock is a situation where each thread is waiting for resources held by other waiting threads. This situation causes the thread to fail to start, which causes the program to pause and break the code at runtime.
It's no surprise that this one pops up often in Java Thread interview questions.
A Deadlock situation can be detected by running the executable code on cmd and subsequently collecting the thread dump. If a deadlock situation is present, the cmd will throw up a message.
This is one of the most common Java Multithreading interview questions asked in technical interviews.
Deadlock situations in Java can be avoided by:
By way of avoiding nested thread locks and providing locks to only one thread at a time can help in reducing the risk of deadlock occurrence.
By using thread join – this function helps the thread to wait for other threads to execute before its own execution, thereby preventing multiple threads from waiting for resources used by other threads.
Individual threads do have their stacks in multithreaded programming. Each thread is independent of the other and maintains its own stack in the memory.
Thready safety can be achieved if multiple threads can use a particular class function without the occurrence of the race condition. In Multithreaded programming, thread safety can be achieved by:
Atomic operations are performed in a single task unit without interfering with other operations. In multi-threaded environments, atomic operations are required to avoid data inconsistencies. int is not an atomic operation. So, when one thread reads this value and increments it by one, the other thread reads the original value, resulting in an incorrect result.
To solve this problem, we need to make sure that the number of sum operations is atomic. We can do this using synchronization, but java.util.concurrent.atomic in Java 5 provides wrapper classes for int and long that can be used to achieve this. atomically without synchronization.
In synchronization, we don’t know how much time a thread will get a chance after a previous thread has released the lock. This can lead to the problem of starvation whereas, in the case of the lock, we have its implementing class reentrant lock which has one of its constructors which lets you pass fairness property as one of its arguments that let the longest waiting thread get the chance to acquire the lock.
In synchronization, if a thread is waiting for another thread, then the waiting thread won’t do any other activity which doesn’t require lock access but with the lock interface, there is a trylock() method with which you can try to access the lock and if you don’t get the lock you can perform other alternate tasks. This helps to improve the performance of the application.
There is no API to check how many threads are waiting for a particular lock whereas this is possible with lock interface implementation class ReentrantLock methods.
Using the lock interface One can get better control of locks, with the methods such as holdCount() method which is not found with synchronization.
One of the most frequently posed Thread interview questions, be ready for it.
Java 5 introduced the Executor framework with the java.util.concurrent. Executor interface. The Executor Framework is a framework for standardizing the invocation, scheduling, execution and management of asynchronous tasks according to execution conventions. Creating many threads without a maximum limit can cause the application to run out of memory and hence the application will crash.
So creating a ThreadPool is a better solution because a limited number of threads can be pooled and reused once they are put again in the thread pool. The Executor framework makes it easy to create thread pools in java for multi-threading applications.
This is a frequently asked question in Java Multithreading interview questions for experienced.
Actually, Java 5 introduced java.util.concurrent.Callable interface in concurrency package that is similar to Runnable interface but can return any Object and throw Exception. The Callable interface uses java generics to define the return type of the Object. Executors class provides useful methods to execute Callable in a thread pool.
Since callable tasks run parallel, we have to wait for the returned Object. Callable tasks return java.util.concurrent.Future object. Using Future we can find out the status of the Callable task and get the returned Object. It provides the get() method that can wait for the Callable to finish and then return the result.
Thread or process context switching is basically an important feature of multithreading. It is referred to as switching of CPU from one thread or process to another one. It allows multiple processes to share the same CPU cores. In context switching, the state of thread or process is stored on PCB or TCB, so that the execution of the thread can be resumed later if required.
FutureTask is the base implementation class of the Future interface and we can use it with Executors for asynchronous processing. Most of the time we don't need to use FutureTask class but it comes really handy if we want to override some of the methods of the Future interface and want to keep most of the base implementation. We can just extend this class and override the methods according to our requirements.
Expect to come across this popular question in Java multithreading questions.
BlockingQueue is typically used for one thread to create objects to be consumed by another thread. Here is a diagram that illustrates this principle:
The "producing thread" continues to create new objects and add them to the BlockingQueue until the queue reaches some upper limit. It's a limit, in other words. When the blocking queue reaches its upper limit, the creating thread is blocked from adding a new object. It remains blocked until the consuming thread lives the object.
"Consumer thread" removes objects from the block queue to process them. If a consuming thread tries to remove an object from an empty queue, the consuming thread is blocked until the producing thread enqueues the object.
CyclicBarrier and CountDownLatch, both required to handle multi-threaded programming. But there are differences between them as shown below:
It's no surprise that this one pops up often in Multithreading interview questions.
The Executors class provides helper methods for the Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes. The Executors class can be used to easily create a thread pool in Java and is also the only class that supports running Callable applications.
Some important concurrent API enhancements are:
Interthread communication, as the name suggests, is a process or mechanism that allows multiple threads to communicate with each other. It is specifically used in Java to prevent thread polling and can be obtained by the wait(), notify() and notifyAll() methods.
ConcurrentHashMap also provides non-locking numbers, unlike Hashtable. Therefore, ConcurrentHashMap is considered faster than Hashtable, especially when the number of readers is more than the number of writers.
Expect to come across this popular question in Java Multithreading interview questions for experienced.
A semaphore is considered a thread synchronization construct that is typically needed to control and manage access to a shared resource using counters. It just sets the thread limit. The semaphore class is defined in the java.util.concurrent package and can be used to send signals between threads to prevent missing signals or to protect critical parts. It can also be used to implement resources or a limited pool.
So nothing happens unless we override the run() method. The compiler does not show an error. This calls the run() method of the thread class and we just don't get the result because the run() method has an empty implementation.
Example:
class ThreadExample extends Thread { //don't override run() method } public class DontOverrideRun { public static void main(String[] args) { System.out.println("Main thread has started"); ThreadExample thread1=new ThreadExample (); thread1.start(); System.out.println("Main thread has completed"); } }
Output:
Main thread has started Main thread has completed
Multithreading is a concept that appears in many programming languages. Although multithreaded languages can run on a single thread, multithreading cannot be disabled in languages that do not support this feature. C, JAVA, C# etc. are languages that support multithreading. JavaScript is a single-threaded language.
While preparing for java developer positions, it becomes necessary to prepare java multithreading interview questions as it is one of the interesting and tricky topics where the interviewer checks the ability how you think to improve the performance of multithreaded applications and overall resource consumption.
Always answer the multi-threading questions by providing the right use cases for the asked questions. Be precise and concise with the concepts and answers. If you don’t know some concepts, then try to revise those using this IQA.
Once you learn and master the multithreading interview questions provided in this IQA, you should try to drive the interviews toward the topics that you know the best.
If possible, you should also aim to build some sample applications so that you can get a complete understanding and working of threads.
Once you know the basics, you start learning intermediate and advanced questions. One should note that just reading and learning the questions isn't sufficient, and hence you should also practice the programs given in this IAQ. Practice more and more multithreading coding questions.
You should start with basic multi-threading questions where you should get familiar with the whats and hows of multithreading. The multithreading questions in java is a good way to go about it.
Multithreading is a core concept for Java developers. When employers are interviewing for a Java developer position, they will likely want to know the extent of your multi-threaded knowledge. You can work on this by practicing Python multithreading interview questions.
You should start reading basic and entry-level multi-threaded interview questions and practice threading sample interview questions and examples. Once you are comfortable with the basics, choose intermediate topics and learn them thoroughly. As soon as you have gained enough knowledge about basic and intermediate topics, you can start with advanced topics, including Android multithreading interview questions.
As part of your interview preparation, take the time to review common interview questions about multithreading to demonstrate your experience and skills to the hiring manager. Make sure you practice multithreading coding interview questions for this. Earn Java certification and stay updated on multithreading.
Interviewers start asking about how much comfortable you are on multithreading topics. We are dividing topics that are expected to know at 3 levels:
1. Beginner Level Concepts
Processes and Threads, Process and thread context block, heaps and stacks, how to create threads using Thread class and Runnable interfaces, critical section, race condition, starvation and deadlocks, class level object and object level locks(monitor), synchronized block and methods, static block and static method with synchronized keywords, primitive data variable thread safety, what is main thread and thread states.
2. Intermediate Level Concepts
Lock interface, when to use atomic keyword and volatile keywords, count down latch, cyclic barrier, cache coherence, producer and consumer problem, thread communication, what are wait(), notify() and notifyAll() methods, why these methods are in the object class, Thread states and how a thread transition to these states, reentrant lock.
3. Advanced Concepts
Multithreading interview questions for experienced often include the executor and ExecutorService frameworks and their mechanism, Executors working, thread scheduling algorithms, threading synchronization using semaphores, ScheduledExecutorService, thread pool, etc.
Multithreading is essential for every programming language and for building modern software applications. Multithreading also leads to minimization and more efficient use of computing resources like optimized zed CPU usage, less memory footprint, and higher efficiency of over applications. Also, the application responsiveness is improved as requests from one thread do not block requests from other threads.
Multithreading makes an application execute multiple tasks in parallel and thus use optimal resources for better throughput and enhanced efficiency. This article has discussed the most important java multithreading interview questions at all levels, and these frequently asked interview questions and answers can help you clear the multithreading interviews. Enroll in a Programming class and stay ahead of the crowd. This will help your CV land in interviews.
Submitted questions and answers are subjecct to review and editing,and may or may not be selected for posting, at the sole discretion of Knowledgehut.
Get a 1:1 Mentorship call with our Career Advisor
By tapping submit, you agree to KnowledgeHut Privacy Policy and Terms & Conditions