Java-Multithreading Interview Questions & Answers

4 avg. rating (80% score) - 1 votes

Are you prepared in attending an interview? Then do not worry, we’ve a right answer for your job interview preparation. If you are preparing for Java-Multithreading job interview and don’t know how to crack interview and what level or difficulty of questions to be asked in job interviews then go through Wisdomjobs Java-Multithreading interview questions and answers page to crack your job interview. Multithreading in java is a process of executing multiple threads simultaneously. Thread is basically a lightweight sub-process, a smallest unit of processing. Multiprocessing and multithreading, both are used to achieve multitasking. They don't allocate separate memory area so saves memory. Below is the list of frequently asked Java-Multithreading interview questions and answers which gets you ready to face the interviews:

A thread is a lightweight sub process. It is an independent path of execution. A thread is executed inside a process and one process can have multiple threads. All the threads inside a process shares a common memory area. Since threads are independent, if an exception occurs in one thread, it doesn’t affect other threads. Threads are used to take advantage of multiple CPU cores available in a machine.

Yes, we can call run() method of a Thread class but it will behave like a normal method and a new thread will not be created to execute the run() method. In this case the run() method will be executed in the same thread which called the run method. To actually execute it in a new Thread, we need to start it using Thread.start() method.

Every thread has a priority, usually higher priority thread gets precedence in execution but it depends on Thread Scheduler implementation that is OS dependent. We can specify the priority of thread using Thread’s setPriority(int) method but it doesn’t guarantee that higher priority thread will get executed before lower priority thread. Thread priority is an int whose value varies from 1 to 10 where 1 is the lowest priority and 10 is the highest priority.

Daemon threads are non-user threads. They are typically used to carry out low-priority tasks that should not take priority over the main task of the program. They can be used to do useful work when all other user threads are blocked. The garbage collector is one example of a daemon thread.JVM terminates itself when all non-daemon threads (user threads) finishes their execution, JVM does not care even if some Daemon threads are running. If JVM finds running daemon thread (upon completion of user threads), it terminates the thread and after that shutdowns itself. You can make a user thread to Daemon by using setDaemon() method of thread class.A child thread created from daemon thread is also a daemon thread.

By default a thread created in a Java program is always a user thread however we can make it daemon by calling setDaemon(true) method, if needed. A daemon thread runs in the background and doesn’t prevent JVM from terminating. As soon as all user thread finishes execution, Java program or JVM terminates itself, JVM doesn’t wait for daemon thread to finish their execution. As soon as last non daemon thread finished, JVM terminates no matter how many Daemon thread exists or running inside JVM.

volatile is a special modifier which is used to indicate that a variable’s value will be modified by different threads. The volatile keyword will mark a Java variable as “being stored in main memory”. The value of this variable will never be cached locally: all reads and writes will go straight to “main memory”. Volatile variable guarantees that a write will happen before any subsequent read. Access to the variable acts as though it is enclosed in a synchronized block.

yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute. If there is no waiting thread or all the waiting threads have a lower priority than the current thread, then the same thread will continue its execution. When the yielded thread will get the chance for execution is decided by the thread scheduler whose behavior is platform dependent.

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing, t.join() causes the current thread(the thread which calls t.join(), mostly the main thread) to pause execution until t’s thread terminates.

notify() method wakes up a single thread that is waiting on this object’s monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is random and occurs at the discretion of the implementation. notifyAll() wakes up all threads that are waiting on this object’s monitor. A thread waits on an object’s monitor by calling one of the wait methods.

In Java, wait and notify methods acts as synchronization utility and are essential methods for inter thread communication. Hence these methods are defined in Object class so that every object will have access to it. Also every Object has a monitor and Locks are made available on per Object basis. This is another reason why wait and notify is declared in Object class rather then Thread class.

No, constructor cannot be synchronized. Constructor is used for instantiating object and when we are in constructor, object is under creation. So, until object is not instantiated it does not need any synchronization.

When an unchecked exception has occurred in the run() method, the thread is stopped by the Java Virtual Machine. It is possible to catch this exception by registering an instance that implements the interface UncaughtExceptionHandler as an exception handler. The handler can be registered by invoking the static method Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler) or by invoking setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler) on the thread instance which tells the JVM to use the provided handler in case there was no specific handler registered on the thread.

In programming, an atomic operation is one that effectively happens all at once. An atomic operation cannot stop in the middle: it either happens completely, or it doesn’t happen at all. No side effects of an atomic operation are visible until the action is complete.In Java,

Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).

Reads and writes are atomic for all variables declared volatile (including long and double variables).

all operations of java.concurrent.Atomic* classes

Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible.

If a thread has been instantiated but not started its is said to be in new state. Unless until a start() method is invoked on the instance of the thread, it will not said to be alive. If you do not call a start() method on the newly created thread instance thread is not considered to be alive. If the start() method is not invoked and the run() method is directly called on the Thread instance, the code inside the run() method will not run in a separate new thread but it will start running in the existing thread.

The different states of threads are as follows:New – When a thread is instantiated it is in New state until the start() method is called on the thread instance. In this state the thread is not considered to be alive.Runnable – The thread enters into this state after the start method is called in the thread instance. The thread may enter into the Runnable state from Running state. In this state the thread is considered to be alive.Running – When the thread scheduler picks up the thread from the Runnable thread’s pool, the thread starts running and the thread is said to be in Running state.Waiting/Blocked/Sleeping – In these states the thread is said to be alive but not runnable. The thread switches to this state because of reasons like wait method called or sleep method has been called on the running thread or thread might be waiting for some i/o resource so blocked.Dead – When the thread finishes its execution i.e. the run() method execution completes, it is said to be in dead state. A dead state can not be started again. If a start() method is invoked on a dead thread a runtime exception will occur.

synchronized keyword can be applied to static/non-static methods or a block of code. Only one thread at a time can access synchronized methods and if there are multiple threads trying to access the same method then other threads have to wait for the execution of method by one thread. Synchronized keyword provides a lock on the object and thus prevents race condition. E.g.public void synchronized method(){} public void synchronized staticmethod(){} public void myMethod(){ synchronized (this){ //synchronized keyword on block of code } }

When a synch non static method is called a lock is obtained on the object. When a synch static method is called a lock is obtained on the class and not on the object. The lock on the object and the lock on the class donâ€™t interfere with each other. It means, a thread accessing a synch non static method, then the other thread can access the synch static method at the same time but canâ€™t access the synch non static method.

In general each thread has its own copy of variable, such that one thread is not concerned with the value of same variable in the other thread. But sometime this may not be the case. Consider a scenario in which the count variable is holding the number of times a method is called for a given class irrespective of any thread calling, in this case irrespective of thread access the count has to be increased so the count variable is declared as volatile.The copy of volatile variable is stored in the main memory, so every time a thread access the variable even for reading purpose the local copy is updated each time from the main memory. The volatile variable also have performance issues.

yield() method pauses the currently executing thread temporarily for giving a chance to the remaining waiting threads of the same priority to execute. If there is no waiting thread or all the waiting threads have a lower priority then the same thread will continue its execution. The yielded thread when it will get the chance for execution is decided by the thread scheduler whose behavior is vendor dependent. If doesn't release the lock on the objects acquired.sleep() allows the thread to go to sleep state for x milliseconds. When a thread goes into sleep state it doesn’t releases the lock.

wait() is a method of Object class. sleep() is a method of Thread class.

sleep() allows the thread to go to sleep state for x milliseconds. When a thread goes into sleep state it doesn’t release the lock. wait() allows thread to release the lock and goes to suspended state. The thread is only active when a notify() or notifAll() method is called for the same object.

The process of executing multiple threads simultaneously is known as multithreading. Java supports multithreading. The main advantage of multithreading is reducing CPU idle time and improving the CPU utilization. This makes the job to be completed in less time.

1.If we instantiate a thread it is called in new state until the Start() method is called.2.If we don't call a start() method for that thread instance, the thread is not called alive.3.If we invoke run method without calling the start method for a thread instance, the code in run() method wil not be executed by a new thread but it will be executed by the existing thread only.

Thread leak is when application does not release references of the thread object and those threads do not get garbage collected.

Number of such unused threads increases with time and it can cause issues in the application like long response time.

To overcome this problem we can do the following1. By maintaining a log for all entry and exit point of thread.2. Check how the new thread is created and how it is closed.3. By using exception handling etc.

Collections provide the method parallelStream() to create a stream that is processed by a thread pool. Alternatively you can call the intermediate method parallel() on a given stream to convert a sequential stream to a parallel counterpart.

The thread pool used for parallel stream operations can be accessed by ForkJoinPool.commonPool(). This way we can query its level of parallelism with commonPool.getParallelism(). The level cannot be changed at runtime but it can be configured by providing the following JVM parameter: -Djava.util.concurrent.ForkJoinPool.common.parallelism=5.

The methods of Hashtable are all synchronized. This is not the case for the HashMap implementation. Hence Hashtable is thread-safe whereas HashMap is not thread-safe. For single-threaded applications it is therefore more efficient to use the “newer” HashMap implementation.

A prominent example for such optimizations is a List implementation that holds the number of elements as a separate variable. This improves the performance for single-threaded applications as the size() operation does not have to iterate over all elements but can return the current number of elements directly. Within a multi-threaded application the additional counter has to be guarded by a lock as multiple concurrent threads may insert elements into the list. This additional lock can cost performance when there are more updates to the list than invocations of the size() operation.

As memory is shared between different threads, ThreadLocal provides a way to store and retrieve values for each thread separately. Implementations of ThreadLocal store and retrieve the values for each thread independently such that when thread A stores the value A1 and thread B stores the value B1 in the same instance of ThreadLocal, thread A later on retrieves value A1 from this ThreadLocal instance and thread B retrieves value B1.

Instances of ThreadLocal can be used to transport information throughout the application without the need to pass this from method to method. Examples would be the transportation of security/login information within an instance of ThreadLocal such that it is accessible by each method. Another use case would be to transport transaction information or in general objects that should be accessible in all methods without passing them from method to method.