Java MultiThreading
Java MultiThreading
Java MultiThreading
Introduction
Concurrency in Java is one of the most complex and advanced topics brought up during technical
interviews. This article provides answers to some of the interview questions on the topic that you
may encounter.
Both processes and threads are units of concurrency, but they have a fundamental difference:
processes do not share a common memory, while threads do.
From the operating system’s point of view, a process is an independent piece of software that
runs in its own virtual memory space. Any multitasking operating system (which means almost
any modern operating system) has to separate processes in memory so that one failing process
wouldn’t drag all other processes down by scrambling common memory.
The processes are thus usually isolated, and they cooperate by the means of inter-process
communication which is defined by the operating system as a kind of intermediate API.
On the contrary, a thread is a part of an application that shares a common memory with other
threads of the same application. Using common memory allows to shave off lots of overhead,
design the threads to cooperate and exchange data between them much faster.
Q2. How can you create a Thread instance and run it?
To create an instance of a thread, you have two options. First, pass a Runnable instance to its
constructor and call start(). Runnable is a functional interface, so it can be passed as a lambda
expression:
Thread also implements Runnable, so another way of starting a thread is to create an anonymous
subclass, override its run() method, and then call start():
1
Thread thread2 = new Thread() {
2 @Override
3 public void run() {
4 System.out.println("Hello World from subclass!");
5 }
6};
thread2.start();
7
Q3. Describe the different states of a Thread and when do the state transitions
occur.
The state of a Thread can be checked using the Thread.getState() method. Different states of a
Thread are described in the Thread.State enum. They are:
NEW — a new Thread instance that was not yet started via Thread.start()
RUNNABLE — a running thread. It is called runnable because at any given time it could
be either running or waiting for the next quantum of time from the thread scheduler. A
NEW thread enters the RUNNABLE state when you call Thread.start() on it
BLOCKED — a running thread becomes blocked if it needs to enter a synchronized
section but cannot do that due to another thread holding the monitor of this section
WAITING — a thread enters this state if it waits for another thread to perform a
particular action. For instance, a thread enters this state upon calling the Object.wait()
method on a monitor it holds, or the Thread.join() method on another thread
TIMED_WAITING — same as the above, but a thread enters this state after calling
timed versions of Thread.sleep(), Object.wait(), Thread.join() and some other methods
TERMINATED — a thread has completed the execution of its Runnable.run() method
and terminated
Q4. What is the difference between the Runnable and Callable interfaces? How
are they used?
The Runnable interface has a single run method. It represents a unit of computation that has to 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.
Q5. What is a daemon thread, what are its use cases? How can you create a
daemon thread?
A daemon thread is a thread that does not prevent JVM from exiting. When all non-daemon
threads are terminated, the JVM simply abandons all remaining daemon threads. Daemon threads
are usually used to carry out some supportive or service tasks for other threads, but you should
take into account that they may be abandoned at any time.
To start a thread as a daemon, you should use the setDaemon() method before calling start():
Q6. What is the Thread’s interrupt flag? How can you set and check it? How
does it relate to the InterruptedException?
The interrupt flag, or interrupt status, is an internal Thread flag that is set when the thread is
interrupted. To set it, simply call thread.interrupt() on the thread object.
If a thread is currently inside one of the methods that throw InterruptedException (wait, join,
sleep etc.), then this method immediately throws InterruptedException. The thread is free to
process this exception according to its own logic.
If a thread is not inside such method and thread.interrupt() is called, nothing special happens. It
is thread’s responsibility to periodically check the interrupt status using static
Thread.interrupted() or instance isInterrupted() method. The difference between these methods
is that the static Thread.interrupt() clears the interrupt flag, while isInterrupted() does not.
Q7. What are Executor and ExecutorService? What are the differences between
these interfaces?
ExecutorService extends the Executor interface with multiple methods for handling and checking
the lifecycle of a concurrent task execution service (termination of tasks in case of shutdown)
and methods for more complex asynchronous task handling including Futures.
For more info on using Executor and ExecutorService, see the article A Guide to Java
ExecutorService.
Q9. What is Java Memory Model (JMM)? Describe its purpose and basic ideas.
Java Memory Model is a part of Java language specification described in Chapter 17.4. It
specifies how multiple threads access common memory in a concurrent Java application, and
how data changes by one thread are made visible to other threads. While being quite short and
concise, JMM may be hard to grasp without strong mathematical background.
The need for memory model arises from the fact that the way your Java code is accessing data is
not how it actually happens on the lower levels. Memory writes and reads may be reordered or
optimized by the Java compiler, JIT compiler, and even CPU, as long as the observable result of
these reads and writes is the same.
This can lead to counter-intuitive results when your application is scaled to multiple threads
because most of these optimizations take into account a single thread of execution (the cross-
thread optimizers are still extremely hard to implement). Another huge problem is that the
memory in modern systems is multilayered: multiple cores of a processor may keep some non-
flushed data in their caches or read/write buffers, which also affects the state of the memory
observed from other cores.
To make things worse, the existence of different memory access architectures would break the
Java’s promise of “write once, run everywhere”. Happily for the programmers, the JMM
specifies some guarantees that you may rely upon when designing multithreaded applications.
Sticking to these guarantees helps a programmer to write multithreaded code that is stable and
portable between various architectures.
Actions, these are inter-thread actions that can be executed by one thread and detected by
another thread, like reading or writing variables, locking/unlocking monitors and so on
Synchronization actions, a certain subset of actions, like reading/writing a volatile
variable, or locking/unlocking a monitor
Program Order (PO), the observable total order of actions inside a single thread
Synchronization Order (SO), the total order between all synchronization actions — it
has to be consistent with Program Order, that is, if two synchronization actions come one
before another in PO, they occur in the same order in SO
synchronizes-with (SW) relation between certain synchronization actions, like unlocking
of monitor and locking of the same monitor (in another or the same thread)
Happens-before Order — combines PO with SW (this is called transitive closure in set
theory) to create a partial ordering of all actions between threads. If one action happens-
before another, then the results of the first action are observable by the second action (for
instance, write of a variable in one thread and read in another)
Happens-before consistency — a set of actions is HB-consistent if every read observes
either the last write to that location in the happens-before order, or some other write via
data race
Execution — a certain set of ordered actions and consistency rules between them
For a given program, we can observe multiple different executions with various outcomes. But if
a program is correctly synchronized, then all of its executions appear to be sequentially
consistent, meaning you can reason about the multithreaded program as a set of actions
occurring in some sequential order. This saves you the trouble of thinking about under-the-hood
reorderings, optimizations or data caching.
Q10. What is a volatile field and what guarantees does the JMM hold for such
field?
A volatile field has special properties according to the Java Memory Model (see Q9). The reads
and writes of a volatile variable are synchronization actions, meaning that they have a total
ordering (all threads will observe a consistent order of these actions). A read of a volatile
variable is guaranteed to observe the last write to this variable, according to this order.
If you have a field that is accessed from multiple threads, with at least one thread writing to it,
then you should consider making it volatile, or else there is a little guarantee to what a certain
thread would read from this field.
Another guarantee for volatile is atomicity of writing and reading 64-bit values (long and
double). Without a volatile modifier, a read of such field could observe a value partly written by
another thread.
A write to an int (32-bit) variable is guaranteed to be atomic, whether it is volatile or not. A long
(64-bit) variable could be written in two separate steps, for example, on 32-bit architectures, so
by default, there is no atomicity guarantee. However, if you specify the volatile modifier, a long
variable is guaranteed to be accessed atomically.
The increment operation is usually done in multiple steps (retrieving a value, changing it and
writing back), so it is never guaranteed to be atomic, wether the variable is volatile or not. If you
need to implement atomic increment of a value, you should use classes AtomicInteger,
AtomicLong etc.
Q12. What special guarantees does the JMM hold for final fields of a class?
JVM basically guarantees that final fields of a class will be initialized before any thread gets hold
of the object. Without this guarantee, a reference to an object may be published, i.e. become
visible, to another thread before all the fields of this object are initialized, due to reorderings or
other optimizations. This could cause racy access to these fields.
This is why, when creating an immutable object, you should always make all its fields final, even
if they are not accessible via getter methods.
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.
1synchronized(object) {
2 // ...
3}
A synchronized instance method has the same semantics, but the instance itself acts as a monitor.
For a static synchronized method, the monitor is the Class object representing the declaring
class.
If the method is an instance method, then the instance acts as a monitor for the method. Two
threads calling the method on different instances acquire different monitors, so none of them gets
blocked.
If the method is static, then the monitor is the Class object. For both threads, the monitor is the
same, so one of them will probably block and wait for another to exit the synchronized method.
Q15. What is the purpose of the wait, notify and notifyAll methods of the Object
class?
A thread that owns the object’s monitor (for instance, a thread that has entered a synchronized
section guarded by the object) may call object.wait() to temporarily release the monitor and give
other threads a chance to acquire the monitor. This may be done, for instance, to wait for a
certain condition.
When another thread that acquired the monitor fulfills the condition, it may call object.notify() or
object.notifyAll() and release the monitor. The notify method awakes a single thread in the
waiting state, and the notifyAll method awakes all threads that wait for this monitor, and they all
compete for re-acquiring the lock.
The following BlockingQueue implementation shows how multiple threads work together via the
wait-notify pattern. If we put an element into an empty queue, all threads that were waiting in the
take method wake up and try to receive the value. If we put an element into a full queue, the put
method waits for the call to the get method. The get method removes an element and notifies the
threads waiting in the put method that the queue has an empty place for a new item.
Q16. Describe the conditions of deadlock, livelock, and starvation. Describe the
possible causes of these conditions.
Deadlock is a condition within a group of threads that cannot make progress because every
thread in the group has to acquire some resource that is already acquired by another thread in the
group. The most simple case is when two threads need to lock both of two resources to progress,
the first resource is already locked by one thread, and the second by another. These threads will
never acquire a lock to both resources and thus will never progress.
Starvation is a case of a thread unable to acquire resource because other thread (or threads)
occupy it for too long or have higher priority. A thread cannot make progress and thus is unable
to fulfill useful work.
The fork/join framework allows parallelizing recursive algorithms. The main problem with
parallelizing recursion using something like ThreadPoolExecutor is that you may quickly run out
of threads because each recursive step would require its own thread, while the threads up the
stack would be idle and waiting.
The fork/join framework entry point is the ForkJoinPool class which is an implementation of
ExecutorService. It implements the work-stealing algorithm, where idle threads try to “steal”
work from busy threads. This allows to spread the calculations between different threads and
make progress while using fewer threads than it would require with a usual thread pool.
1. Overview
The fork/join framework was presented in Java 7. It provides tools to help speed up parallel
processing by attempting to use all available processor cores – which is accomplished through a
divide and conquer approach.
In practice, this means that the framework first “forks”, recursively breaking the task into
smaller independent subtasks until they are simple enough to be executed asynchronously.
After that, the “join” part begins, in which results of all subtasks are recursively joined into a
single result, or in the case of a task which returns void, the program simply waits until every
subtask is executed.
To provide effective parallel execution, the fork/join framework uses a pool of threads called the
ForkJoinPool, which manages worker threads of type ForkJoinWorkerThread.
2. ForkJoinPool
The ForkJoinPool is the heart of the framework. It is an implementation of the ExecutorService
that manages worker threads and provides us with tools to get information about the thread pool
state and performance.
Worker threads can execute only one task at the time, but the ForkJoinPool doesn’t create a
separate thread for every single subtask. Instead, each thread in the pool has its own double-
ended queue (or deque, pronounced deck) which stores tasks.
This architecture is vital for balancing the thread’s workload with the help of the work-stealing
algorithm.
Simply put – free threads try to “steal” work from deques of busy threads.
By default, a worker thread gets tasks from the head of its own deque. When it is empty, the
thread takes a task from the tail of the deque of another busy thread or from the global entry
queue, since this is where the biggest pieces of work are likely to be located.
This approach minimizes the possibility that threads will compete for tasks. It also reduces the
number of times the thread will have to go looking for work, as it works on the biggest available
chunks of work first.
In Java 8, the most convenient way to get access to the instance of the ForkJoinPool is to use its
static method commonPool(). As its name suggests, this will provide a reference to the common
pool, which is a default thread pool for every ForkJoinTask.
According to Oracle’s documentation, using the predefined common pool reduces resource
consumption, since this discourages the creation of a separate thread pool per task.
The same behavior can be achieved in Java 7 by creating a ForkJoinPool and assigning it to a
public static field of a utility class:
1public static ForkJoinPool forkJoinPool = new ForkJoinPool(2);
With ForkJoinPool’s constructors, it is possible to create a custom thread pool with a specific
level of parallelism, thread factory, and exception handler. In the example above, the pool has a
parallelism level of 2. This means that pool will use 2 processor cores.
3. ForkJoinTask<V>
ForkJoinTask is the base type for tasks executed inside ForkJoinPool. In practice, one of its two
subclasses should be extended: the RecursiveAction for void tasks and the RecursiveTask<V> for
tasks that return a value. They both have an abstract method compute() in which the task’s logic
is defined.
In the example below, the unit of work to be processed is represented by a String called
workload. For demonstration purposes, the task is a nonsensical one: it simply uppercases its
input and logs it.
To demonstrate the forking behavior of the framework, the example splits the task if
workload.length() is larger than a specified threshold using the createSubtask() method.
The String is recursively divided into substrings, creating CustomRecursiveTask instances which
are based on these substrings.
This pattern can be used to develop your own RecursiveAction classes. To do this, create an
object which represents the total amount of work, chose a suitable threshold, define a method to
divide the work, and define a method to do the work.
3.2. RecursiveTask<V>
For tasks that return a value, the logic here is similar, except that resulting for each subtask is
united in a single result:
In this example, the work is represented by an array stored in the arr field of the
CustomRecursiveTask class. The createSubtask() method recursively divides the task into
smaller pieces of work until each piece is smaller than the threshold. Then, the invokeAll()
method submits subtasks to the common pull and returns a list of Future.
In this example, this is accomplished using Java 8’s Stream API; the sum() method is used as a
representation of combining sub results into the final result.
The submit() or execute() method (their use cases are the same):
1forkJoinPool.execute(customRecursiveTask);
2int result = customRecursiveTask.join();
The invoke() method forks the task and waits for the result, and doesn’t need any manual
joining:
The invokeAll() method is the most convenient way to submit a sequence of ForkJoinTasks to
the ForkJoinPool. It takes tasks as parameters (two tasks, var args, or a collection), forks them
returns a collection of Future objects in the order in which they were produced.
Alternatively, you can use separate fork() and join() methods. The fork() method submits a task
to a pool, but it doesn’t trigger its execution. The join() method is be used for this purpose. In the
case of RecursiveAction, the join() returns nothing but null; for RecursiveTask<V>, it returns the
result of the task’s execution:
1customRecursiveTaskFirst.fork();
2result = customRecursiveTaskLast.join();
To avoid confusion, it is generally a good idea to use invokeAll() method to submit more than
one task to the ForkJoinPool.
5. Conclusions
Using the fork/join framework can speed up processing of large tasks, but to achieve this
outcome, some guidelines should be followed:
Use as few thread pools as possible – in most cases, the best decision is to use one
thread pool per application or system
Use the default common thread pool, if no specific tuning is needed
Use a reasonable threshold for splitting ForkJoingTask into subtasks
Avoid any blocking in your ForkJoingTasks
Thread is a lightweight subprocess. Thread class belongs to java.lang package.Threads have their own
stack.It's a way to take advantage of multiple cpu available in a machine. For example, if one thread
takes 50 milliseconds to do a job, you can use 10 threads to reduce that task to 5 milliseconds.
A process can have many threads. Threads can execute any part of process.And same part of Process
can be executed by multiple threads.
Processes have their own address while Thread share the address space of the process that created it.
Thread has its own stack while in process all threads share a common system resource like heap
memory.
Q4 What are the differences between implementing Runnable and extending Thread while creating a
thread in java? Which one is better?
When we implement Runnable interface we can extend any other class as well but if we extends Thread
class we can not extends any other class because java does not allow multiple inheritance.
You can find here the detailed answer of difference between implementing Runnable and extends
Thread.
When we create a Thread instance in a java program, then its state is new. Then we start the Thread,
then it's state changes to Runnable(ready to run but not running yet).Execution of Threads depends
upon ThreadScheduler. ThreadScheduler is responsible to allocate CPUs to threads in Runnable thread
pool and change their state to Running.Waiting,Blocked and Dead are the remaining states of the
Thread.
So in short new,runnable,running.waiting,blocked and dead are the states a Thread can be in.
Wait method releases the lock while sleep method doesn't release the lock.
Wait method belongs to java.lang.Object class while sleep method belongs to java.lang.Thread class.
You can find the detailed answer here difference between wait and sleep method in java.
Q7 What is the difference between starting a thread with start() method and run() method?
This question is a bit tricky and might confuse you as well. The answer is when you call start() method,
main method internally calls run() method to start newly created Thread, so run method is ultimately
called by newly created Thread.
When you call run() method, its called in the same thread, no new thread is started which is the case
when you call start() method.
When we create a thread in java program, then it is called as user thread. We can not make a user
thread to daemon thread if a thread is started.
The daemon threads are the low priority threads that provide the background support to the user
threads.It provides services to the user threads. A child thread created from a daemon thread is also a
daemon thread.
When we make a variable volatile, then all the threads reads its value directly from the memory and
don't cache it. This make sure the shared variables are consistently updated.
No, there is no possibility to start a thread twice. If we do so , then it will throw an Exception.
Synchronization is the capability to control the access of multiple threads to any shared resource.
The main advantage of synchronization is
a. to avoid consistency problem
b. to avoid thread interference
Synchronized block is the more preferred way because it doesn't lock the object while synchronized
methods lock the object. Synchronized method will stop multiple synchronized blocks in the class, even
though they are not related, from the execution and put them in the wait state to get the lock on the
object.
Sleep method throws the interrupted exception if another thread interrupts the sleeping thread while
yield method does not throw the interrupted exception.
Thread.sleep() method does not cause currently executing thread to give up monitors while yield
method gives up the monitor.
You can find detailed explanation of difference between sleep and yield method in java.
Deadlock is a situation where two threads are waiting for each other to release locks holded by them on
resources.For example
You can find the answer here Program to create a deadlock in java.
1. Lock specific member variables of the class rather than locking whole class.
2. Use join() method, if possible try to use join method ,although it may refrain us from taking full
advantage of multithreading environment because threads will start and end sequentially, but it can be
handy in avoiding deadlocks.
3. If possible try to avoid nested synchronization blocks.
Every thread has a priority. Its value is int which ranges from 1 to 10 where 1 being the lowest priority
and 10 being the highest priority.
Usually higher priority threads get higher precedence in execution but it depends on the
ThreadScheduler implementation which is OS dependent.
We can specify the priority of thread but it does not guarantee that higher priority thread will get
executed before the lower priority thread.
Q19 What is the difference between class lock and object lock?
Threads can acquire object lock by entering synchronized methods.Threads can acquire lock on class's
class object by entering the static synchronized methods.
Multiple objects of class may exist and every Object has its own lock.In class lock multiple objects
of class may exist but there is always one class's class object lock available.
Callable throws checked exception while Runnable does not throw checked exception.
Return type of Runnable is void that is it does not return any value while Callable can return a Future
object.
You can find the detailed explanation of difference between callable and runnable.
Q21 What is the difference between time slicing and preemptive scheduling?
In preemptive scheduling the higher priority task executes until it enters the waiting or dead states or
higher priority task comes into existence. In time slicing, a task runs for a predefined slice of time and
then reenters the pool of ready tasks.
Q23 What is race condition in java and how we can solve it?
When more than one thread try to access same resource without synchronization causes race condition.
We can solve race condition by using a synchronized block or synchronized method.
Threads can communicate with each other using wait(), notify(), notifyAll() methods.
Q25 Why wait(), notify() and notifyAll() method have to be called from the synchronized context?
When a Thread calls wait() on any Object, it must have the monitor on Object that it will leave and goes
in wait state until any other Thread call notify() on this Object. Similarly when a thread calls notify() on
any Object, it leaves the monitor on the Object and other waiting threads can get the monitor on the
Object. Since all these threads require Thread to have a Object monitor,that can be achieved only by
synchronization.That is why wait(),notify() and notifyAll() method have to be called from the
synchronized context.
ThreadLocal can be used to create ThreadLocal variables. We know that all threads of an Object shares
its variables.So if the variable is not thread safe then we can use synchronization. If we want to avoid
synchronization then we can use ThreadLocal variables.
Each thread has its own ThreadLocal variable and they can use it's get() and set() methods to get the
default value or change its value local to Thread.
Threadpool manages the pool of worker threads. There is a queue in which the tasks are keep waiting
for execution.
Q28 Can you find whether thread holds lock() on an object or not?
holdsLock(Object) method can be used to determine whether current thread holds the lock on monitor
of specified object.
The method holdsLock(Object) returns true if the thread holds lock or monitor of the specified object.
Answer.
Threads consumes CPU in best possible manner, hence enables multi processing. Multi
threading reduces idle time of CPU which improves performance of application.
We can create multiple threads in java, even if we don’t create any Thread, one Thread at
least do exist i.e. main thread.
Advantage of Thread : Suppose one thread needs 10 minutes to get certain task, 10
threads used at a time could complete that task in 1 minute, because threads can run
parallely.
Thread are subdivision of Process. One or more Threads runs in the context of process. Threads
can execute any part of process. And same part of process can be executed by multiple Threads.
Processes have their own copy of the data segment of the parent process while Threads have
direct access to the data segment of its process.
Processes have their own address while Threads share the address space of the process that
created it.
Process creation needs whole lot of stuff to be done, we might need to copy whole parent
process, but Thread can be easily created.
Processes can easily communicate with child processes but interprocess communication is
difficult. While, Threads can easily communicate with other threads of the same process using
wait() and notify() methods.
In process all threads share system resource like heap Memory etc. while Thread has its own
stack.
Any change made to process does not affect child processes, but any change made to thread can
affect the behavior of the other threads of the process.
Example to see where threads on are created on different processes and same process.
Answer. This is very basic threading question. Threads can be created in two ways i.e. by
implementing java.lang.Runnable interface or extending java.lang.Thread class and then
extending run method.
Thread has its own variables and methods, it lives and dies on the heap. But a thread of execution
is an individual process that has its own call stack. Thread are lightweight process in java.
2) And then create Thread object by calling constructor and passing reference of Runnable
interface i.e. runnable object :
Answer. Yes, Threads have their own stack. This is very interesting question, where interviewer
tends to check your basic knowledge about how threads internally maintains their own stacks.
I’ll be explaining you the concept by diagram.
Question 5. We should implement Runnable interface or extend Thread class. What are
differences between implementing Runnable and extending Thread?
Answer. Well the answer is you must extend Thread only when you are looking to modify run()
and other methods as well. If you are simply looking to modify only the run() method
implementing Runnable is the best option (Runnable interface has only one abstract method i.e.
run() ).
Answer. The solution to question is quite simple, Thread behaviour is unpredictable because
execution of Threads depends on Thread scheduler, thread scheduler may have different
implementation on different platforms like windows, unix etc. Same threading program may
produce different output in subsequent executions even on same platform.
To achieve we are going to create 2 threads on same Runnable Object, create for loop in run()
method and start both threads. There is no surety that which threads will complete first, both
threads will enter anonymously in for loop.
Answer. Threads are lightweight process only if threads of same process are executing
concurrently. But if threads of different processes are executing concurrently then threads are
heavy weight process.
Question 8. How can you ensure all threads that started from main must end in order in
which they started and also main should end in last? (Important)
Answer. Interviewers tend to know interviewees knowledge about Thread methods. So this is
time to prove your point by answering correctly. We can use join() methodto ensure all threads
that started from main must end in order in which they started and also main should end in last.In
other words waits for this thread to die. Calling join() method internally calls join(0);
DETAILED DESCRIPTION : Join() method - ensure all threads that started from main must end
in order in which they started and also main should end in last. Types of join() method with
programs- 10 salient features of join.
Question 9.What is difference between starting thread with run() and start() method?
(Important)
Answer. This is quite interesting question, it might confuse you a bit and at time may make you
think is there really any difference between starting thread with run() and start() method.
When you call start() method, main thread internally calls run() method to start newly created
Thread, so run() method is ultimately called by newly created thread.
When you call run() method main thread rather than starting run() method with newly thread it
start run() method by itself.
Question 10. What is significance of using Volatile keyword? (Important)
Answer. Java allows threads to access shared variables. As a rule, to ensure that shared variables
are consistently updated, a thread should ensure that it has exclusive use of such variables by
obtaining a lock that enforces mutual exclusion for those shared variables.
If a field is declared volatile, in that case the Java memory model ensures that all threads see a
consistent value for the variable.
1. No, synchronized can be used only with methods, i.e. in method declaration.
Question 11. Differences between synchronized and volatile keyword in Java? (Important)
1. Volatilecan be used as a keyword against the variable, we cannot use volatile against
method declaration.
Synchronized method:
Synchronized block:
void method2(){
synchronized (this) {
}
Synchronized variable (illegal):
1. Volatile does not acquire any lock on variable or object, but Synchronization acquires
lock on method or block in which it is used.
1. Volatile variables are not cached, but variables used inside synchronized method or block
are cached.
1. When volatile is used will never create deadlock in program, as volatile never obtains any
kind of lock . But in case if synchronization is not done properly, we might end up
creating dedlock in program.
1. Synchronization may cost us performance issues, as one thread might be waiting for
another thread to release lock on object. But volatile is never expensive in terms of
performance.
Thinking of starting thread again and calling start() method on it (which internally is going to
call run() method) for us is some what like asking dead man to wake up and run. As, after
completing his life person goes to dead state.
Question 13. What is race condition in multithreading and how can we solve it?
(Important)
Answer. This is very important question, this forms the core of multi threading, you should be
able to explain about race condition in detail. When more than one thread try to access same
resource without synchronization causes race condition.
So we can solve race condition by using either synchronized block or synchronized method.
When no two threads can access same resource at a time phenomenon is also called as mutual
exclusion.
Few sub questions>
When two threads try to read on same resource without synchronization, it’s never going to
create any problem.
When two threads try to write to same resource without synchronization, it’s going to create
synchronization problems.
Answer. This is very must know question for all the interviewees, you will most probably face
this question in almost every time you go for interview.
Threads can communicate with each other by using wait(), notify() and notifyAll() methods.
Question 15. Why wait(), notify() and notifyAll() are in Object class and not in Thread
class? (Important)
Answer.
1. Every Object has a monitor, acquiring that monitors allow thread to hold lock on object.
But Thread class does not have any monitors.
1. wait(), notify() and notifyAll()are called on objects only >When wait() method is called
on object by thread it waits for another thread on that object to release object monitor by
calling notify() or notifyAll() method on that object.
When notify() method is called on object by thread it notifies all the threads
which are waiting for that object monitor that object monitor is available now.
So, this shows that wait(), notify() and notifyAll() are called on objects only.
Now, Straight forward question that comes to mind is how thread acquires object lock by
acquiring object monitor? Let’s try to understand this basic concept in detail?
1. Wait(), notify() and notifyAll() method being in Object class allows all the threads
created on that object to communicate with other. .
2. As multiple threads exists on same object. Only one thread can hold object monitor at a
time. As a result thread can notify other threads of same object that lock is available now.
But, thread having these methods does not make any sense because multiple threads
exists on object its not other way around (i.e. multiple objects exists on thread).
3. Now let’s discuss one hypothetical scenario, what will happen if Thread class contains
wait(), notify() and notifyAll() methods?
Having wait(), notify() and notifyAll() methods means Thread class also must have their
monitor.
>Synchronization on object won’t be possible- Because object has monitor, one object can have
multiple threads and thread hold lock on object by holding object monitor. But if each thread will
have monitor, we won’t have any way of achieving synchronization.
Question 16. Is it important to acquire object lock before calling wait(), notify() and
notifyAll()?
Answer.Yes, it’s mandatory to acquire object lock before calling these methods on object. As
discussed above wait(), notify() and notifyAll() methods are always called from Synchronized
block only, and as soon as thread enters synchronized block it acquires object lock (by holding
object monitor). If we call these methods without acquiring object lock i.e. from outside
synchronize block then java.lang. IllegalMonitorStateException is thrown at runtime.
Wait() method needs to enclosed in try-catch block, because it throws compile time exception
i.e. InterruptedException.
Question 17. How can you solve consumer producer problem by using wait() and notify()
method? (Important)
Answer. Here come the time to answer very very important question from interview perspective.
Interviewers tends to check how sound you are in threads inter communication. Because for
solving this problem we got to use synchronization blocks, wait() and notify() method very
cautiously. If you misplace synchronization block or any of the method, that may cause your
program to go horribly wrong. So, before going into this question first i’ll recommend you to
understand how to use synchronized blocks, wait() and notify() methods.
>Producer will produce total of 10 products and cannot produce more than 2 products at a time
until products are being consumed by consumer.
Example> when sharedQueue’s size is 2, wait for consumer to consume (consumer will consume
by calling remove(0) method on sharedQueue and reduce sharedQueue’s size). As soon as size is
less than 2, producer will start producing.
>Consumer can consume only when there are some products to consume.
Example> when sharedQueue’s size is 0, wait for producer to produce (producer will produce by
calling add() method on sharedQueue and increase sharedQueue’s size). As soon as size is
greater than 0, consumer will start consuming.
We will create sharedQueue that will be shared amongst Producer and Consumer. We will now
start consumer and producer thread.
Note: it does not matter order in which threads are started (because rest of code has taken care of
synchronization and key points mentioned above)
consumerThread.start();
consumerThread will enter run method and call consume() method. There it will check for
sharedQueue’s size.
-if size is equal to 0 that means producer hasn’t produced any product, wait for producer to
produce by using below piece of code-
synchronized (sharedQueue) {
while (sharedQueue.size() == 0) {
sharedQueue.wait();
-if size is greater than 0, consumer will start consuming by using below piece of code.
synchronized (sharedQueue) {
Thread.sleep((long)(Math.random() * 2000));
sharedQueue.notify();
}
Than we will start producerThread >
producerThread.start();
producerThread will enter run method and call produce() method. There it will check for
sharedQueue’s size.
-if size is equal to 2 (i.e. maximum number of products which sharedQueue can hold at a time),
wait for consumer to consume by using below piece of code-
synchronized (sharedQueue) {
sharedQueue.wait();
-if size is less than 2, producer will start producing by using below piece of code.
synchronized (sharedQueue) {
sharedQueue.add(i);
Thread.sleep((long)(Math.random() * 1000));
sharedQueue.notify();
Question 18. How to solve Consumer Producer problem without using wait() and notify()
methods, where consumer can consume only when production is over.?
Answer. In this problem, producer will allow consumer to consume only when 10 products have
been produced (i.e. when production is over).
We will approach by keeping one boolean variable productionInProcess and initially setting it to
true, and later when production will be over we will set it to false.
Question 19. How can you solve consumer producer pattern by using BlockingQueue?
(Important)
Answer. Now it’s time to gear up to face question which is most probably going to be followed
up by previous question i.e. after how to solve consumer producer problem using wait() and
notify() method. Generally you might wonder why interviewer's are so much interested in asking
about solving consumer producer problem using BlockingQueue, answer is they want to know
how strong knowledge you have about java concurrent Api’s, this Api use consumer producer
pattern in very optimized manner, BlockingQueue is designed is such a manner that it offer us
the best performance.
Answer. This is very important question from interview perspective. But, what makes this
question important is it checks interviewees capability of creating and detecting deadlock. If you
can write a code to form deadlock, than I am sure you must be well capable in solving that
deadlock as well. If not, later on this post we will learn how to solve deadlock as well.
First question comes to mind is, what is deadlock in multi threading program?
Deadlock is a situation where two threads are waiting for each other to release lock holded by
them on resources.
Thread-1 acquires lock on String.class and then calls sleep() method which gives Thread-2 the
chance to execute immediately after Thread-1 has acquired lock on String.class and Thread-2
acquires lock on Object.class then calls sleep() method and now it waits for Thread-1 to release
lock on String.class.
Conclusion:
Now, Thread-1 is waiting for Thread-2 to release lock on Object.class and Thread-2 is waiting
for Thread-1 to release lock on String.class and deadlock is formed.
synchronized (String.class) {
Thread.sleep(100);
synchronized (Object.class) {
publicvoid run() {
synchronized (Object.class) {
Thread.sleep(100);
synchronized (String.class) {
Here comes the important part, how above formed deadlock could be solved :
Thread-1 acquires lock on String.class and then calls sleep() method which gives Thread-2 the
chance to execute immediately after Thread-1 has acquired lock on String.class and Thread-2
tries to acquire lock on String.class but lock is holded by Thread-1. Meanwhile, Thread-1
completes successfully. As Thread-1 has completed successfully it releases lock on String.class,
Thread-2 can now acquire lock on String.class and complete successfully without any deadlock
formation.
publicvoid run() {
synchronized (String.class) {
Thread.sleep(100);
synchronized (Object.class) {
}
}
publicvoid run() {
synchronized (String.class) {
Thread.sleep(100);
synchronized (Object.class) {
1. Lock specific member variables of class rather than locking whole class: We must try to
lock specific member variables of class rather than locking whole class.
1. Use join() method: If possible try touse join() method, although it may refrain us from
taking full advantage of multithreading environment because threads will start and end
sequentially, but it can be handy in avoiding deadlocks.
Question 21. Have you ever generated thread dumps or analyzed Thread Dumps?
(Important)
Answer. Answering this questions will show your in depth knowledge of Threads. Every
experienced must know how to generate Thread Dumps.
VisualVM is most popular way to generate Thread Dump and is most widely used by
developers. It’s important to understand usage of VisualVM for in depth knowledge of
VisualVM. I’ll recommend every developer must understand this topic to become master in
multi threading.
It helps us in analyzing threads performance, thread states, CPU consumed by threads, garbage
collection and much more. For detailed information see Generating and analyzing Thread
Dumps using VisualVM - step by step detail to setup VisualVM with screenshots
jstack is very easy way to generate Thread dump and is widely used by developers. I’ll
recommend every developer must understand this topic to become master in multi threading. For
creating Thread dumps we need not to download any jar or any extra software. For detailed
information see Generating and analyzing Thread Dumps using JSATCK - step by step detail to
setup JSTACK with screenshots.
Question 22. What is life cycle of Thread, explain thread states? (Important)
Answer. Thread states/ Thread life cycle is very basic question, before going deep into concepts
we must understand Thread life cycle.
New
Runnable
Running
Waiting/blocked/sleeping
Terminated (Dead)
Running : Thread scheduler selects thread to go fromrunnable to running state. In running state
Thread starts executing by entering run() method.
>Thread is still alive, but currently it’s not eligible to run. In other words.
By calling wait()method thread go from running to waiting state. In waiting state it will wait for
other threads to release object monitor/lock.
By calling sleep() methodthread go from running to sleeping state. In sleeping state it will wait
for sleep time to get over.
Terminated (Dead) : A thread is considered dead when its run() method completes.
Question 23. Are you aware of preemptive scheduling and time slicing?
Answer. In preemptive scheduling, the highest priority thread executes until it enters into the
waiting or dead state.
In time slicing, a thread executes for a certain predefined time and then enters runnable pool.
Than thread can enter running state when selected by thread scheduler.
Answer.Daemon threads are low priority threads which runs intermittently in background for
doing garbage collection.
Daemon threads are service oriented threads, they serves all other threads.
These threads are created before user threads are created and die after all other user
threads dies.
Priority of daemon threads is always 1 (i.e. MIN_PRIORITY).
we can use isDaemon() method to check whether thread is daemon thread or not.
we can use setDaemon(boolean on) method to make any user method a daemon thread.
You may like to see how daemon threads work, for that you can use VisualVM or jStack.
I have provided Thread dumps over there which shows daemon threads which were
intermittently running in background.
Some of the daemon threads which intermittently run in background are >
Answer.Suspend() method is deadlock prone. If the target thread holds a lock on object when it
is suspended, no thread can lock this object until the target thread is resumed. If the thread that
would resume the target thread attempts to lock this monitor prior to calling resume, it results in
deadlock formation.
Suspend() method puts thread from running to waiting state. And thread can go from waiting to
runnable state only when resume() method is called on thread. It is deprecated method.
Resume() method is only used with suspend() method that’s why it’s also deprecated method.
Answer. This question is again going to check your in depth knowledge of thread methods i.e.
destroy() method is deadlock prone. If the target thread holds a lock on object when it is
destroyed, no thread can lock this object (Deadlock formed are similar to deadlock formed when
suspend() and resume() methods are used improperly). It results in deadlock formation. These
deadlocksare generally called Frozen processes.
Additionally you must know calling destroy() method on Threads throw runtimeException i.e.
NoSuchMethodError. Destroy() method puts thread from running to dead state.
Question 27. As stop() method is deprecated, How can we terminate or stop infinitely
running thread in java? (Important)
Answer. This is very interesting question where interviewees thread basics basic will be tested.
Interviewers tend to know user’s knowledge about main thread’s and thread invoked by main
thread.
We will try to address the problem by creating new thread which will run infinitely until certain
condition is satisfied and will be called by main Thread.
Stopping a thread with Thread.stop() causes it to release all of the monitors that it has locked. If
any of the objects previously protected by these monitors were in an inconsistent state, the
damaged objects become visible to other threads, which might lead to unpredictable behavior.
Question 28. what is significance of yield() method, what state does it put thread in?
yield() is a native method it’s implementation in java 6 has been changed as compared to its
implementation java 5. As method is native it’s implementation is provided by JVM.
In java 5, yield() method internally used to call sleep() method giving all the other threads of
same or higher priority to execute before yielded thread by leaving allocated CPU for time gap of
15 millisec.
But java 6, calling yield() method gives a hint to the thread scheduler that the current thread is
willing to yield its current use of a processor. The thread scheduler is free to ignore this hint. So,
sometimes even after using yield() method, you may not notice any difference in output.
Definition : yield() method when called on thread gives a hint to the thread scheduler that
the current thread is willing to yield its current use of a processor.The thread scheduler is
free to ignore this hint.
Thread state : when yield() method is called on thread it goes from running to runnable
state, not in waiting state. Thread is eligible to run but not running and could be picked
by scheduler at anytime.
synchronized block : thread need not to to acquire object lock before calling
yield()method i.e. yield() method can be called from outside synchronized block.
Question 29.What is significance of sleep() method in detail, what statedoes it put thread in
?
Definition : sleep() methods causes current thread to sleep for specified number of
milliseconds (i.e. time passed in sleep method as parameter). Ex- Thread.sleep(10) causes
currently executing thread to sleep for 10 millisec.
Thread state : when sleep() is called on thread it goes from running to waiting state and
can return to runnable state when sleep time is up.
Exception : sleep() method must catch or throw compile time exception i.e.
InterruptedException.
1. sleep(long millis, int nanos) - Causes the currently executing thread to sleep for the
specified number of milliseconds plus the specified number of nanoseconds.
static method : sleep()is a static method, causes the currently executing thread to sleep for
the specified number of milliseconds.
Answer.
Should be called from synchronized block :wait() method is always called from
synchronized block i.e. wait() method needs to lock object monitor before object on
which it is called. But sleep() method can be called from outside synchronized block i.e.
sleep() method doesn’t need any object monitor.
Belongs to which class : wait() method belongs to java.lang.Object class but sleep()
method belongs to java.lang.Thread class.
Called on object or thread : wait() method is called on objects but sleep() method is called
on Threads not objects.
Thread state : when wait() method is called on object, thread that holded object’s monitor
goes from running to waiting state and can return to runnable state only when notify() or
notifyAll()method is called on that object. And later thread scheduler schedules that
thread to go from from runnable to running state.
when sleep() is called on thread it goes from running to waiting state and can return to runnable
state when sleep time is up.
When called from synchronized block :when wait() method is called thread leaves the
object lock. But sleep()method when called from synchronized block or method thread
doesn’t leaves object lock.
Answer.
Definition : yield() method when called on thread gives a hint to the thread scheduler that
the current thread is willing to yield its current use of a processor.The thread scheduler is
free to ignore this hint. sleep() methods causes current thread to sleep for specified
number of milliseconds (i.e. time passed in sleep method as parameter). Ex-
Thread.sleep(10) causes currently executing thread to sleep for 10 millisec.
Thread state : when sleep() is called on thread it goes from running to waiting state and
can return to runnable state when sleep time is up. when yield() method is called on
thread it goes from running to runnable state, not in waiting state. Thread is eligible to
run but not running and could be picked by scheduler at anytime.
Exception : yield() method need not to catch or throw any exception. But sleep() method
must catch or throw compile time exception i.e. InterruptedException.
Waiting time : yield() method stops thread for unpredictable time, that depends on thread
scheduler. But sleep() method have got few options.
1. sleep(long millis) - Causes the currently executing thread to sleep for the specified
number of milliseconds
2. sleep(long millis, int nanos) - Causes the currently executing thread to sleep for
the specified number of milliseconds plus the specified number of nanoseconds.
> yield() and sleep() method can be called from outside synchronized block.
> yield() and sleep() method are called on Threads not objects.
Question 32. Mention some guidelines to write thread safe code, most important point we
must take care of in multithreading programs?
Answer. In multithreading environment it’s important very important to write thread safe code,
thread unsafe code can cause a major threat to your application. I have posted many articles
regarding thread safety. So overall this will be revision of what we have learned so far i.e.
writing thread safe healthy code and avoiding any kind of deadlocks.
1. Even static variables are not thread safe, they are used in static methods and if static
methods are not synchronized then thread on same or different object can enter method
concurrently. Multiple threads may exist on same or different objects of class but only
one thread can enter static synchronized method at a time, we must consider making
static methods as synchronized.
1. If possible, try to use volatile variables. If a field is declared volatile all threads see a
consistent value for the variable. Volatile variables at times can be used as alternate to
synchronized methods as well.
1. Final variables are thread safe because once assigned some reference of object they
cannot point to reference of other object.
void method(){
final inti=0;
void method(){
1. Usage of local variables : If possible try to use local variables, local variables are thread
safe, because every thread has its own stack, i.e. every thread has its own local variables
and its pushes all the local variables on stack.
void method(){
1. Using thread safe collections : Rather than using ArrayList we must Vector and in place
of using HashMap we must use ConcurrentHashMap or HashTable.
2. We must use VisualVM or jstack to detect problems such as deadlocks and time taken
by threads to complete in multi threading programs.
3. Using ThreadLocal:ThreadLocal is a class which provides thread-local variables. Every
thread has its own ThreadLocal value that makes ThreadLocal value threadsafe as well.
4. Rather than StringBuffer try using immutable classes such as String. Any change to
String produces new String.
Question 33. How thread can enter waiting, sleeping and blocked state and how can they go
to runnable state ?
Answer. This is very prominently asked question in interview which will test your knowledge
about thread states. And it’s very important for developers to have in depth knowledge of this
thread state transition. I will try to explain this thread state transition by framing few sub
questions. I hope reading sub questions will be quite interesting.
By calling wait()method thread go from running to waiting state. In waiting state it will wait for
other threads to release object monitor/lock.
Once notify() or notifyAll()method is called object monitor/lock becomes available and thread
can again return to runnable state.
By calling sleep() methodthread go from running to sleeping state. In sleeping state it will wait
for sleep time to get over.
Once specified sleep time is up thread can again return to runnable state.
Suspend() method can be used to put thread in waiting state and resume() method is the only way
which could put thread in runnable state.
Thread also may go from running to waiting state if it is waiting for some I/O operation to take
place. Once input is available thread may return to running state.
>When threads are in running state, yield()method can make thread to go in Runnable state.
Question 34. Difference between notify() and notifyAll() methods, can you write a code to
prove your point?
Answer. Goodness. Theoretically you must have heard or you must be aware of differences
between notify() and notifyAll().But have you created program to achieve it? If not let’s do it.
First, I will like give you a brief description of what notify() and notifyAll() methods do.
notify()- 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. A thread waits on an object's monitor by calling one of the
wait methods.
The awakened threads will not be able to proceed until the current thread relinquishes the lock on
this object.
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.
The awakened threads will not be able to proceed until the current thread relinquishes the lock on
this object.
Question 35. Does thread leaves object lock when sleep() method is called?
Answer. When sleep() method is called Thread does not leaves object lock and goes from
running to waiting state. Thread waits for sleep time to over and once sleep time is up it goes
from waiting to runnable state.
Question 36. Does thread leaves object lock when wait() method is called?
Answer. When wait() method is called Thread leaves the object lock and goes from running to
waiting state. Thread waits for other threads on same object to call notify() or notifyAll() and
once any of notify() or notifyAll() is called it goes from waiting to runnable state and again
acquires object lock.
Answer. This question will test your basic knowledge how start and run methods work internally
in Thread Api.
When we call start() method on thread, it internally calls run() method with newly created thread.
So, if we don’t override run() method newly created thread won’t be called and nothing will
happen.
publicclass DontOverrideRun {
thread1.start();
/*OUTPUT
*/
As we saw in output, we didn’t override run() method that’s why on calling start() method
nothing happened.
Answer. This question will again test your basic core java knowledge how overriding works at
runtime, what what will be called at runtime and how start and run methods work internally in
Thread Api.
When we call start() method on thread, it internally calls run() method with newly created thread.
So, if we override start() method, run() method will not be called until we write code for calling
run() method.
@Override
publicvoid run() {
@Override
publicvoid start(){
System.out.println("In start() method");
publicclass OverrideStartMethod {
thread1.start();
/*OUTPUT
In start() method
*/
If we note output. we have overridden start method and didn’t called run() method from it, so,
run() method wasn’t call.
Question 39. Can we acquire lock on class? What are ways in which you can acquire lock
on class?
Answer. Yes, we can acquire lock on class’s class object in 2 ways to acquire lock on class.
synchronized (MyClass.class) {
As soon as thread entered Synchronization method, thread acquired lock on class’s class object.
Answer. It is very important question from multithreading point of view. We must understand
difference between object lock and class lock to answer interview, ocjp answers correctly.
Question 41. Suppose you have 2 threads (Thread-1 and Thread-2) on same object. Thread-1 is
in synchronized method1(), can Thread-2 enter synchronized method2() at same time?
Question 42. Suppose you have 2 threads (Thread-1 and Thread-2) on same object. Thread-1 is
in static synchronized method1(), can Thread-2 enter static synchronized method2() at same
time?
Answer.No, here when Thread-1 is in static synchronized method1() it must be holding lock on
class class’s object and will release lock on class’s classobject only when it exits static
synchronized method1(). So, Thread-2 will have to wait for Thread-1 to release lock on class’s
classobject so that it could enter static synchronized method2().
Likewise, Thread-2 even cannot enter static synchronized method1() which is being executed by
Thread-1. Thread-2 will have to wait for Thread-1 to release lock on class’s classobject so that it
could enter static synchronized method1(). Now, let’s see a program to prove our point.
Question 43. Suppose you have 2 threads (Thread-1 and Thread-2) on same object. Thread-1 is
in synchronized method1(), can Thread-2 enter static synchronized method2() at same time?
Question 44. Suppose you have thread and it is in synchronized method and now can thread
enter other synchronized method from that method?
Answer.Yes, here when thread is in synchronized method it must be holding lock on object’s
monitor and using that lock thread can enter other synchronized method. Now, let’s see a
program to prove our point.
Question 45. Suppose you have thread and it is in static synchronized method and now can
thread enter other static synchronized method from that method?
Answer. Yes, here when thread is in static synchronized method it must be holding lock on
class’s class object and using that lock thread can enter other static synchronized method. Now,
let’s see a program to prove our point.
Question 46. Suppose you have thread and it is in static synchronized method and now can
thread enter other non static synchronized method from that method?
Answer.Yes, here when thread is in static synchronized method it must be holding lock on
class’s class object and when it enters synchronized method it will hold lock on object’s monitor
as well.
So, now thread holds 2 locks (it’s also called nested synchronization)-
>first one on class’s class object.
>second one on object’s monitor (This lock will be released when thread exits non static
method).Now, let’s see a program to prove our point.
Question 47. Suppose you have thread and it is in synchronized method and now can thread
enter other static synchronized method from that method?
Answer.Yes, here when thread is in synchronized method it must be holding lock on object’s
monitor and when it enters static synchronized method it will hold lock on class’s class object as
well.
So, now thread holds 2 locks (it’s also called nested synchronization)-
>second one on class’s class object.(This lock will be released when thread exits static
method).Now, let’s see a program to prove our point.
Question 48. Suppose you have 2 threads (Thread-1 on object1 and Thread-2 on object2).
Thread-1 is in synchronized method1(), can Thread-2 enter synchronized method2() at same
time?
Likewise, Thread-2 even enter synchronized method1() as well which is being executed by
Thread-1 (because threads are created on different objects). Now, let’s see a program to prove
our point.
Question 49. Suppose you have 2 threads (Thread-1 on object1 and Thread-2 on object2).
Thread-1 is in static synchronized method1(), can Thread-2 enter static synchronized method2()
at same time?
Answer.No, it might confuse you a bit that threads are created on different objects. But, not to
forgot that multiple objects may exist but there is always one class’s class object lock available.
Here, when Thread-1 is in static synchronized method1() it must be holding lock on class class’s
object and will release lock on class’s classobject only when it exits static synchronized
method1(). So, Thread-2 will have to wait for Thread-1 to release lock on class’s classobject so
that it could enter static synchronized method2().
Likewise, Thread-2 even cannot enter static synchronized method1() which is being executed by
Thread-1. Thread-2 will have to wait for Thread-1 to release lock on class’s classobject so that it
could enter static synchronized method1(). Now, let’s see a program to prove our point.
Question 50. Difference between wait() and wait(long timeout), What are thread states when
these method are called?
Answer.
Question 51. How can you implement your own Thread Pool in java?
Answer.
What is ThreadPool?
ThreadPool is a pool of threads which reuses a fixed number of threads to execute tasks.
At any point, at most nThreads threads will be active processing tasks. If additional tasks are
submitted when all threads are active, they will wait in the queue until a thread is available.
In this post i will be using LinkedBlockingQueue provide by java Api, you can refer this post for
implementing ThreadPool using custom LinkedBlockingQueue.
Need/Advantage of ThreadPool?
Instead of creating new thread every time for executing tasks, we can create ThreadPool which
reuses a fixed number of threads for executing tasks.
Then, threads will enter run() method of ThreadPoolsThread class and will call take() method on
taskQueue.
If tasks are available thread will execute task by entering run() method of task (As tasks
executed always implements Runnable).
publicvoid run() {
...
while (true) {
...
runnable.run();
...
...
When execute() method of ThreadPool is called, it internally calls put() method on taskQueue to
add tasks.
taskQueue.put(task);
Once tasks are available all waiting threads are notified that task is available.
What is ThreadLocal ?
ThreadLocal is a class which provides thread-local variables. Every thread has its own
ThreadLocal value that makes ThreadLocal value threadsafe as well.
Yes, ThreadLocal variables are thread safe. As every thread has its own ThreadLocal value and
one thread can’t see other threads ThreadLocal value.
Application of ThreadLocal?
1. ThreadLocal are used by many web frameworks for maintaining some context (may be
session or request) related value.
o In any single threaded application, same thread is assigned for every request made
to same action, so ThreadLocal values will be available in next request as well.
o In multi threaded application, different thread is assigned for every request made
to same action, so ThreadLocal values will be different for every request.
1. When threads have started at different time they might like to store time at which they
have started. So, thread’s start time can be stored in ThreadLocal.
We will create instance of ThreadLocal. ThreadLocal is a generic class, i will be using String to
demonstrate threadLocal.
All threads will see same instance of ThreadLocal, but a thread will be able to see value which
was set by it only.
threadLocal.get()
Answer.
When one thread loops continuously waiting for another thread to signal.
Performance point of view - Busy spin is very bad from performance point of view, because one
thread keeps on looping continuously ( and consumes CPU) waiting for another thread to signal.
We must use sleep() or wait() and notify() method. Using wait() is better option.
Why using wait() and notify() is much better option to solve busy spin?
Because in case when we use sleep() method, thread will wake up again and again after specified
sleep time until boolean variable is true. But, in case of wait() thread will wake up only when
when notified by calling notify() or notifyAll(), hence end up consuming CPU in best possible
manner.
Consumer thread continuously execute (busy spin) in while loop tillproductionInProcess is true.
Once producer thread has ended it will make boolean variable productionInProcess false and
busy spin will be over.
while(productionInProcess){
}
Question 54. Can a constructor be synchronized?
Answer. No, constructor cannot be synchronized. Because constructor is used for instantiating
object, when we are in constructor object is under creation. So, until object is not instantiated it
does not need any synchronization.
Question 55. Can you find whether thread holds lock on object or not?
Answer. holdsLock(object) method can be used to find out whether current thread holds the lock
on monitor of specified object.
holdsLock(object) method returns true if the current thread holds the lock on monitor of
specified object.
Answer. When thread does not enough CPU for its execution Thread starvation happens.
Low priority threads gets less CPU (time for execution) as compared to high priority
threads. Lower priority thread may starve away waiting to get enough CPU to perform
calculations.
In deadlock two threads waits for each other to release lock holded by them on resources.
There both Threads starves away to get CPU.
Thread might be waiting indefinitely for lock on object’s monitor (by calling wait()
method), because no other thread is calling notify()/notifAll() method on object. In that
case, Thread starves away to get CPU.
Thread might be waiting indefinitely for lock on object’s monitor (by calling wait()
method), but notify() may be repeatedly awakening some other threads. In that case also
Thread starves away to get CPU.
Question 57. What is addShutdownHook method in java?
Once JVM’s shutdown has begunnew shutdown hook cannot be registered neither previously-
registered hook can be de-registered. Any attempt made to do any of these operations causes an
IllegalStateException.
For more detail with program read : Threads addShutdownHook method in java
Question 58. How you can handle uncaught runtime exception generated in run method?
Thread.setDefaultUncaughtExceptionHandler(new
Thread.UncaughtExceptionHandler(){
});
Question 59. What is ThreadGroup in java, What is default priority of newly created
threadGroup, mention some important ThreadGroup methods ?
Answer. When program starts JVM creates a ThreadGroup named main. Unless specified,
all newly created threads become members of the main thread group.
getName()
o name of ThreadGroup.
activeGroupCount()
o count of active groups in ThreadGroup.
activeCount()
o count of active threads in ThreadGroup.
list()
o list() method has prints ThreadGroups information
getMaxPriority()
o Method returns the maximum priority of ThreadGroup.
setMaxPriority(int pri)
o Sets the maximum priority of ThreadGroup.
Answer.
Thread class provides variables of final static int type for setting thread priority.
publicfinalstaticintMIN_PRIORITY= 1;
/* The default priority that is assigned to a thread. */
publicfinalstaticintNORM_PRIORITY= 5;
publicfinalstaticintMAX_PRIORITY= 10;
Thread with MAX_PRIORITY is likely to get more CPU as compared to low priority threads.
But occasionally low priority thread might get more CPU. Because thread scheduler schedules
thread on discretion of implementation and thread behaviour is totally unpredictable.
Thread with MIN_PRIORITY is likely to get less CPU as compared to high priority threads. But
occasionally high priority thread might less CPU. Because thread scheduler schedules thread on
discretion of implementation and thread behaviour is totally unpredictable.
Answer:
A thread helps facilitates multi-tasking and multi-processing within a program. It utilizes CPU
effectively and helps improve the performance of the application. Java enables the user to use
multiple threads at a time. It can run in parallel with other programs without any interruptions.
This helps in reducing a time for the process. For example, if a program takes 60 seconds to
execute, we can use 6 threads which will give us the result in 10 seconds.
Java provides two ways to implement thread in a program. interface java.lang.Runnable has an
instance java.lang.A thread which requires a task to execute through an instance. The Thread
class already implements Runnable, so a user can directly override run() method by extending
Thread class or by implementing Runnable interface.
Answer:
Java does not support multiple inheritances of a class, but it allows to implement multiple
interfaces at a time. Therefore, it will be better to implement Runnable than extending Thread
class.
Answer:
A thread is a subset of a process. One process can have multiple threads running for it. Threads
can run any part of a process. A process has its own address where it is stored, while thread
shares the address of the process that has created it. Creating a process is a hectic process while
threads can be created easily. A thread is usually referred as a lightweight process. Interprocess
communication is difficult while threads can communicate easily using the Java methods of
wait() and notify(). Processes are independent, hence any change made to process does not affect
child processes. On the contrary, if changes are made in a thread there are possibilities that other
threads may be affected.
Answer:
The reason for this is the thread scheduler which handles the execution of threads. The scheduler
maybe having different performance on different platforms Windows, UNIX, LINUX, etc. While
executing the same thread may give different outputs on different platforms and sometimes even
on the same platform. To solve this, a user can create the same Runnable object, create run()
loops in both threads and start both threads together. Ideally, the scheduler should pick both
threads together and the performance should not be affected, but both threads will enter loops
anonymously.
Answer:
Java facilitates user to share variables present in different threads. A volatile variable acts as a
special modifier which can be used only for instance variables. As this variable is shared, there
would be consistent changes with it. The thread must ensure that it has exclusive access to these
variables and a lock is compelled for mutual exclusion of shared variables. It ensures that a write
will happen prior to any consequent read. Java memory model ensures the consistency of this
variable. Volatile methods cannot be there as they can be only used in the form of variables.
Answer:
Synchronized keyword is used when the purpose Is to run only one thread at a time in an
appropriate section of code. It can be used to show four types of different blocks as below:
1)Instance methods
2)Static methods
3)Code blocks inside instance methods
4)Code blocks inside static methods
The difference between volatile and synchronized keyword is that synchronized can be used with
variable and methods, while volatile cannot be used with methods. Volatile variables are not
stored in cache memory, synchronized variables are stored in cache memory. A volatile variable
will never land up in deadlock as it does not require to obtain any lock. While in synchronized
variables if they are not done properly then it may end up in deadlock.
7.Why methods like wait(), notify() and notify all() are present in object class and
not in Thread class?
Answer:
Object class has monitors which allow the thread to lock an object, while Thread does not have
any monitors. When any of above methods are called it waits for another thread to release the
object and notifies the monitor by calling notify() or notify all(). When notify() method is called
it does the job of notifying all threads which are waiting for the object to be released. The object
class’s monitor checks for the object if it is available or not. Thread class having these methods
would not help as multiple threads exist on an object and not vice versa.
Answer:
1)sleep() method is called on threads and not objects. Wait() method is called on objects.
2)When wait() method is called then monitor moves the thread from running to waiting state.
Once a thread is in wait() then it can move to runnable only when it has notify() or notifyall() for
that object. The scheduler changes the state after this. While in sleep() method, the state is
changed to wait and will return to runnable only after sleep time is over.
3)Wait() method is a part of java.lang.Object class, while sleep() is a part of java.lang.Thread
class.
4)Wait() is always used with a synchronized block as it requires to lock an object while sleep()
can be used from outside synchronized block.
Answer:
In Java, multithreading one cannot force start a thread. Only thread scheduler can control threads
and they are not exposed to any API for control.
Q10) Does thread leave object lock when wait() and sleep() methods are called?
Answer:
When a thread is in sleep() method it does not leave lock and moves to waiting state. The thread
waits for sleep time to get over. When wait() method is used thread leaves the object lock and
goes to waiting state. Once notify() is called it again goes to running state and acquires the lock.
1. What is Multithreading?
A thread is a sub-process that has a separate path of execution. Each thread runs
independently in its own execution stack. There can be multiple threads in a single process.
Even though the processes execute separately, they share process resources.
First and foremost, Multithreading allows for quick execution of tasks as each thread is
executed independently.
In Multithreading, programs are always ready for input in spite of a background task
running simultaneously.
Since threads share the common resources, the cache memory is more efficiently used.
Server dependency is reduced as one server is capable of executing multiple threads at the
same time.
CPU is never idle waiting for a program thread to free resources. Multiple thread execution
is much better than multiple process execution.
A thread is a sub-process.
Processes have separate memory addresses whereas threads share address space in
memory.
Context switching between processes is faster than context switching between threads.
Since processes don’t share any resources, any change to the parent process won’t affect
the child process whereas changes to the parent thread will impact the child thread.
wait(), notifyall(), notify() methods are used to implement inter thread communication.
The wait() method is provided by the Object class in Java for the purpose of inter thread
communication. Java.lang.Object.wait() is the method to pause the current thread. The
thread is paused until another thread calls the notify() or notifyall() method.
The wait() method must be called from the synchronised method for proper communication
along with notify() and notifyall() methods.
A thread can go through any of the following stages in its life cycle:
New: In the New state, a Thread class is initiated using the New operator but boot yet
started.
Runnable: In this state, the thread is started using the start() method.
Running: This is the state where the thread scheduler picks up the thread from the ready
state and makes in running.
Waiting: This state, also called the Blocked state, is alive but running as it is waiting for
another thread to finish or a resource to free up.
Terminated: A thread is in the dead or terminated state when it exits with the run()
method.
The state of the thread or the process is stored in Context Switching so that it can be
restored and execution resumed at a later point of time. In this way, context switching
facilitates multiple processes to share CPU resource.
There are two ways to create a thread- by extending the thread class or by implementing
the thread class via Interface. The differences in these both methods are:
If we extend from the Thread class, we can’t extend from any other class as Java doesn’t
permit multiple inheritance. But if the Runnable interface is implemented, even the base
class can be extended, if needed.
If we extend from the Thread class, each associated thread can create a unique object.
While implementing a Runnable interface, multiple threads have to share the same object.
There are various inbuilt methods in Thread class such as getPriority(), isAlive and so on
while runnable interface provides only one method, run().
The wait() method has to be defined in the Object class while the sleep() method is defined
in the Thread class.
Implementing the wait() method releases the lock whereas implementing the sleep()
method does not release the lock.
A thread cannot be started twice as once a thread is started and executed, it goes to the
Dead state. If an attempt is made to restart the thread, the compiler will throw a runtime
exception.
When multiple threads are trying to access the same resources, synchronization is needed
to control the access to avoid any consistency issues as well as thread interference.
Java implements the process of synchronization to allow only a single thread to execute at a
time. This prevents errors from multiple thread execution at once.
MyThread(){
t.start();
and then
t.start();
After the new thread is created, it will not start running until you call the start( ) method.
A process has a self-contained execution environment, Threads exist within a process - every
process has at least one.
Process are heavyweight tasks whereas threads are referred as lightweight processes as creating a
new thread requires fewer resources than creating a new process.
Each Process has its own separate address spaces, threads with in the same process share the
process' resources, including memory and open files. This means that it's very easy to share data
amongst threads, but it's also easy for the threads to bump on each other, which can lead to
unpredictable scenarios.
Inter process communication is expensive whereas inter thread communication is inexpensive and
in Java can be achieved easily using wait and notify.
Context switching from one process to another is expensive; context switching between threads is
generally less expensive than in processes.
Threads are easier to create than processes as separate address space is not required for a thread.
Read more about difference between thread and process in Java here.
New - When a thread is created either by extending Thread class or implementing Runnable
interface it is in "New State".
Runnable - When we call start() method on the thread object that causes the thread to begin
execution and it's the Java Virtual Machine that calls the run method of the thread.
Blocked - When a resource is shared among various threads then a thread may go into blocked state
as the resource may be used by another thread.
Waiting - A thread that is waiting indefinitely for another thread to perform a particular action is in
the waiting state.
Timed_Waiting - A thread that is waiting for another thread to perform an action for up to a
specified waiting time is in timed_waiting state.
What are the thread priorities and how to set thread priority?
When a Java thread is created, it inherits its priority from the thread that created it. Thread's priority
can be modified at any time after its creation using the setPriority() method which is a member of
Thread class.
Here newPriority specifies the new priority setting for the calling thread. The priority level ranges
from 1 (least important) to 10 (most important) and the default priority level is 5.
In Thread class, three constants are provided to define min, max and default priority for a thread.
isAlive() method is the member of the Thread class and its general form is -
isAlive() method tests if the thread it is called upon is alive. A thread is alive if it has been started and
has not yet died. The isAlive( ) method returns true if the thread upon which it is called is still running,
otherwise it returns false.
If we have a thread -
Join() method is used when you want to wait for the thread to finish. Its general form is -
When we call start() method on the thread that causes this thread to begin execution and it's the Java
Virtual Machine that calls the run method of this thread.
If we directly call run method it will be treated as a normal overridden method of the thread class (or
runnable interface). This run method will be executed with in the context of the current thread not in a
new thread.
No. A thread can only be started once and any attempt to start the same thread twice will throw
IllegalThreadStateException.
Read more about Can we start the same thread twice here.
What are wait, notify, notifyall method used for in Java multi-threading?
Java provides inter-thread communication using the wait(), notify() and notifyAll() methods of the
Object class.
wait method - tells the current thread (thread which is executing code inside a synchronized
method or block) to give up monitor and go to sleep, until another thread invokes the notify() or
notifyAll() method for this object.
notify method - Wakes up a single thread that is waiting on this object's monitor. If more than one
threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and
occurs at the discretion of the implementation.
notifyAll method - wakes up all the threads that called wait( ) on the same object.
Notify method wakes up a single thread that is waiting to acquire a lock on the object. If more than
one threads are waiting on this object, one of them is chosen to be awakened.
NotifyAll method wakes up all the threads that called wait on the same object. Note that only one
of these threads will get a lock to the object.
wait() and notify() work at the monitor level, thread which is currently holding the monitor is asked to
give up that monitor through wait and through notify (or notifyAll) thread which are waiting on the
object's monitor are notified that thread can wake up. Important point to note here is that monitor is
assigned to an object not to a particular thread. That's one reason why these methods are in Object
class.
wait, notify and notifyAll() are used for inter-thread communication. But threads themselves have no
knowledge of each others status. It is the shared object among the threads that acts as a communicator
among the threads. Threads lock an object, wait on an object and notify an object.
Read more about Why wait(), notify() and notifyAll() methods are in object class here.
When notify method is called does the thread which comes out of waiting start executing instantly?
No, thread which comes out of waiting because of the notify() method will not be able to proceed
until the current thread relinquishes the lock on this object. The awakened thread just changes to the
runnable state and it is ready to be scheduled again. The awakened thread will compete in the usual
manner with any other threads that might be actively competing to synchronize on this object.
wait method tells the current thread (thread which is executing code inside a synchronized method or
block) to give up monitor. Object's lock is acquired by a thread only when it is executing in a
synchronized context. So it makes sense to use wait() method, which asks thread to release the lock only
in synchronized context.
Same way; when object's notify() or notifyAll() method is called, single thread (in case of notify) or all
of the threads (in case of notifyAll), waiting for the object's lock change state to runnable and contend
for the object's lock, and the thread that gets the lock starts execution. Here again, notify and notifyAll
can inform other threads, that the object's lock can be acquired now, only if these methods are called
from the synchronized object.
Read more about Why wait, notify and notifyAll must be called inside a synchronized method or block
here.
Once wait is called on an object the thread that is currently executing with in the synchronized
context waits until notify or notfyAll method is called. But there is a possibility that a waiting thread
resumes again even when notify() or notifyAll() are not called (this will rarely occur in practice). This is
known as spurious wakeup.
To guard against it the recommendation is that; call to wait() method should be with in a loop that
checks the condition on which the thread is waiting.
Yield - A hint to the scheduler that the current thread is willing to yield its current use of a processor.
The scheduler is free to ignore this hint. The executing thread is suspended and the CPU is given to some
other runnable thread. This thread will wait until the CPU becomes available again.Technically, in
process scheduler's terminology, the executing thread is put back into the ready queue of the processor
and waits for its next turn.
yield is a static method of the Thread class. When called it will work on the currently executing thread,
not on any particular thread.
The very first difference is that sleep is defined as a static method in Thread class and operates on
the currently executing thread. Whereas wait() method is in Object class and operates on the thread
which is currently holding the lock on the object on which the wait method is called.
Since wait method is supposed to release the lock on an object so it has to be called from a
synchronized context (with in a synchronized method or synchronized block). If not called from a
synchronized context will result in a IllegalMonitorStateException being thrown. With sleep method
there is no such mandatory condition it doesn't need to be called from a synchronized context.
Wait method will release the lock it holds on an object before going to waiting state which gives
another thread a chance to enter the synchronized block. Sleep method if called from a synchronized
block or method will not release the lock so another won't get a chance to enter the synchronized block.
yield and sleep methods are used to work on the currently executing thread. Thus these methods are
static so that you don't call it on any other thread.
In a multithreaded environment when more than one thread are trying to access a shared resource
we need to have some way to ensure that the resource will be used by only one thread at a time. The
process by which it is ensured is called synchronization.
It is not always needed to synchronize the whole method, let's say we have a 100 line code method,
out of which critical section (shared resource) is only 7 lines then it makes sense to synchronize only
those 7 lines rather than synchronizing the whole method. That is known as synchronized block or
statement.
class Message{
synchronized(this){
System.out.print("**" + msg);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("*");
Deadlock describes a situation where two or more threads are blocked forever, waiting for each
other. To describe it in a simple manner let's assume there are two threads Thread-1 and Thread-2 and
two objects obj1 and obj2. Thread-1 already holds a lock on obj1 and for further processing it needs a
lock on obj2. At the same time Thread-2 holds a lock on obj2 and wants a lock on obj1. In that kind of
scenario both threads will be waiting for each other forever to release lock they are already holding thus
creating a deadlock.
A deadlock can be created by having nested synchronized blocks where lock on objects are acquired in
a reverse manner. i.e. if there are two objects obj1 and obj2 then first thread tries to acquire lock in
sequence obj1 and then obj2. In the same time second thread tries to acquire lock in sequence obj2 first
and then obj1.
class Test{
this.name = name;
return this.name;
}
this.test1 = test1;
this.test2 = test2;
@Override
synchronized(test1){
System.out.println("" + test1.getName());
synchronized(test2){
System.out.println("Reached here");
this.test1 = test1;
this.test2 = test2;
@Override
synchronized(test2){
System.out.println("" + test2.getName());
synchronized(test1){
System.out.println("Reached here");
t1.start();
t2.start();
Thread t1 will start execution of run method in ThreadA and acquire lock on object test1 and then try
to acquire lock on object test2. Meanwhile Thread t2 will start execution of run method in ThreadB and
acquire lock on object test2 and then try to acquire lock on object test1. So both threads are trying to
acquire a lock which is already held by another thread. Thus causing a deadlock.
In Java there is a class called ThreadLocal which provides another way of thread-safety apart from
synchronization. Usually when we have multiple threads sharing an object we need to synchronize the
critical section of the code in order to make it thread safe.
ThreadLocal class provides thread-local variables where each thread that accesses one (via its get or
set method) has its own, independently initialized copy of the variable. Since each and every threadhas
its own copy of the object so explicit synchronization is not needed to provide thread safety.
When a variable is declared as volatile, the compiler (even runtime) seeing the keyword volatile
knows that this variable is shared. So the volatile variables are not cached in registers and read
operation on a volatile variable always returns the most recent write by any thread.
However, synchronization can introduce thread contention. It occurs when two or more threads try to
access the same resource simultaneously but can't get the lock causing the Java runtime to execute one
or more threads slowly, or even suspend their execution.
In any multi-threaded application, you may come across a situation where a thread (or a bunch of
threads) is unable to gain regular access to shared resources and is unable to make progress. This
situation is known as thread starvation.
Thread starvation may happen because other “greedy” threads are gaining the lock and access to the
shared resource resulting in a thread (or a bunch of threads) getting starved of access to shared
resources and CPU time.
If there is an object providing a synchronized method that requires a lots of processing time. If there
is a thread invoking this method quite frequently, other threads that also need to access the
synchronized method will be blocked.
If there are some higher priority threads those threads will get executed first rather than the
threads having lower priority.
If you are using wait-notify signalling, then theoretically a thread that is waiting to get access to a
shared resource may wait indefinitely if always some other thread is notified and get access to the
shared resource.
What is livelock?
Livelock in Java multi-threading is a situation where two or more threads are acting on a response to
an action of each other and not able to make any progress because of that.
How livelock is different from deadlock is that in case of deadlock threads get blocked whereas in case
of livelock threads are active but busy responding to each other thus not making any progress.