Here is list of Java Multithreading interview questions.
Table of Contents
- Java multithreading interview questions
- 1. What is thread in java?
- 2. What is Multithreading?
- 3. What are ways to create a thread in java?
- 4. Thread vs Runnable which is better approach to create a thread?
- 5. What are differences between thread and process?
- 6. What are differences between Sleep and wait in java?
- 7. Why wait(), notify() And notifyAll() methods are in Object Class?
- 8. Why wait and notify method are called from synchronized block?
- 9. Why sleep() and yield() are static methods in Thread class?
- 10. Define states of thread in java?
- 11. Can we call run method directly to start a thread?
- 12. Can we start a thread twice in java?
- 13. How to make a main thread wait until all other threads finished execution?
- 14. What are daemon threads?
- 15. How can you change user thread to daemon thread?
- 16. What is Synchronization?
- 17. What is need of Synchronization?
- 18. Can you explain about Object level locking and class level locking?
- 19. Can two threads execute static and non static methods concurrently?
- 20. If one method of class is synchronized and other method of same class is not synchronized? Can they be executed concurrently by two threads?
- 21. Is it safe to call a synchronized method from another synchronized method?
- 22. What is deadlock?
- 23. What are differences between notify and notifyall?
- 24. What is use of volatile keyword in java?
- 25. You have started 3 threads and you ought to be certain that main thread finish last. How will you get it done?
- 26.How can you print even odd number using 2 threads?
- 27. What is ThreadLocal in java?
- 28. What is Thread dump?
- 29. What happens if you don’t override run() method of Thread class?
- Java Concurrency Interview questions
- 30. What is executor framework?
- 31. What is Thread pool?
- 32. Can you list down important factory methods of Executors class?
- 33. Can you write a code to implement newFixedThreadPool?
- 34. What is BlockingQueue
- 35. What are difference between Runnable and Callable interface in java
- 36. What is Lock interface? What are its advantages over synchronized block?
- 37. What is Condition interface?
- 38. Implement custom BlockingQueue using Lock and Condition?
- 39. What is CountDownLatch?
- 40. What is CyclicBarrier?
- 41. What is Semaphore?
Java multithreading interview questions
1. What is thread in java?
Answer:
Thread can be called as light weight process. It can be referred as smallest part of process which can be executed concurrently with other parts(threads) of process.
2. What is Multithreading?
Answer:
Multithreading is execution of multiple threads concurrently. Java supports multithreading , so it allows your application to perform two or more task concurrently. Multithreading can be of advantage specially when now a days, machine has multiple CPUs, so multiple tasks can be executed concurrently.
3. What are ways to create a thread in java?
Answer:
There are two ways to create a thread in java
- By extending thread class
- By implementing Runnable interface.
Further reading:
4. Thread vs Runnable which is better approach to create a thread?
Implementing Runnable interface is considered to be better approach than Extending Thread due to following reasons.
- Java does not support multiple inheritance so if you extend Thread class and you can not extend any other class which is needed in most of the cases.
- Runnable interface represents a task and this can be executed with help of Thread class or Executors.
- When you use inheritance, it is because you want to extend some properties of parent, modify or improve class behavior. But if you are extending thread class just to create thread, so it may not be recommended behavior for Object Oriented Programming.
5. What are differences between thread and process?
Answer:Â
You can go through difference between process and thread to see the differences.
6. What are differences between Sleep and wait in java?
Parameter
|
wait
|
sleep
|
Synchronized
|
wait should be called from synchronized context i.e. from block or method, If you do not call it using synchronized context, it will throw |
It need not be called from synchronized block or methods
|
Calls on
|
wait method operates on Object and defined in Object class |
Sleep method operates on current thread and is in java.lang.Thread
|
Release of lock
|
wait release lock of object on which it is called and also other locks if it holds any
|
Sleep method does not release lock at all
|
Wake up condition
|
until call notify() or notifyAll() from Object class
|
Until time expires or calls interrupt()
|
static
|
wait is non static method
|
sleep is static method
|
You can refer difference between sleep and wait in java for more details.
7. Why wait(), notify() And notifyAll() methods are in Object Class?
Answer:Â
Thread waits for lock associated with the object and notify other threads which are waiting for same lock.
If wait(), notify() and notifyAll()
will be in thread class, then each thread has to be aware of status of another thread and that does not make sense as each thread runs independent of other thread and has no specific knowledge about other thread.
Why wait(), notify() And notifyAll() methods are in Object Class
8. Why wait and notify method are called from synchronized block?
Answer:Â
wait()
is called, so that thread can wait on some condition. When condition is met, then thread has to give up the lock.
To give up the lock, thread has to own it first. Thread can acquire lock by enter into synchronized context.
If wait method is called outside of synchronized context, then it will throw IllegalMonitorStateException
.
9. Why sleep()
and yield()
are static methods in Thread class?
Answer:Â
You can call sleep()
and yield()
method on current executing thread. If there is in wait
state, you can not call these methods.
To avoid the confusion for programmers, there methods are made static.
10. Define states of thread in java?
There are 5 states of thread in java
11. Can we call run method directly to start a thread?
Answer:Â
No, you can not directly call run method to start a thread. You need to call start method to create a new thread. If you call run method directly , it won’t create a new thread and it will be in same stack as main.
You can refer can we call run method directly to start a thread for more details
12. Can we start a thread twice in java?
Answer:Â
No, Once you have started a thread, it can not be started again. If you try to start thread again , it will throw IllegalThreadStateException.
You can refer can we start thread twice for more details
13. How to make a main thread wait until all other threads finished execution?
Answer:Â
You can make use of join method to achieve above scenario.
You can read more about join method.
14. What are daemon threads?
Answer:
Daemon threads are low-priority background threads which provide services to user threads. Its life depends on user threads. If no user thread is running then JVM can exit even if daemon threads are running. [JVM](JVM “JVM”) does not wait for daemon threads to finish.
15. How can you change user thread to daemon thread?
Answer:setDaemon()
method can be used to mark thread as user thread. If you put setDaemon(true), it makes thread as daemon.
16. What is Synchronization?
Answer:
Synchronization is ability to restrict access to shared resource to only one thread. When two or more threads need access to shared resource, there has to be some mechanism such that shared resource will be used by only one thread. The process by which we can achieve it is called Synchronization.
17. What is need of Synchronization?
Let’s understand this with the help of an example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package org.arpit.java2blog; public class RequestCounter { private int count; public int incrementCount() { count++; return count; } } |
Thread T1
sees count as 20
and increments it to 21
. At the same time, thread t2
also sees count as 20
and increment it to 21
. This shows that count became inconsistent.
You can achieve Synchronization using two ways.
- synchronized method
- synchronized block
You can not use synchronized with  instance or class variables.
synchronized method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package org.arpit.java2blog; public class RequestCounter { private int count; public synchronized int incrementCount() { count++; return count; } } |
Thread T1
sees count as 20 and increments it to 21
. At the same time, Thread t2
will now see count as 21
and increment it to 22
.synchronized block
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package org.arpit.java2blog; public class RequestCounter { private int count; public int incrementCount() { synchronized (this) { count++; return count; } } } |
Thread T1
 sees count as 20 and increment it to 21. At the same time, thread t2 will now see count as 21 and increment it to 22.
18. Can you explain about Object level locking and class level locking?
There are two types of locking in java.
- Object level locking
- Class level locking
You can refer Object level locking and class level locking for more details.
19. Can two threads execute static and non static methods concurrently?
Answer:
Yes, Since two threads will acquire lock on different objects, they can be executed concurrently without any issues.
20. If one method of class is synchronized and other method of same class is not synchronized? Can they be executed concurrently by two threads?
Answer:
Yes, because one thread will require lock to get into synchronized block but second thread which will execute non synchronized method that won’t require any lock, so it can be executed concurrently.
21. Is it safe to call a synchronized method from another synchronized method?
Answer:
Yes, it is safe to call a synchronized method from another synchronized method because when you call synchronized method, you will get lock on this object and when you call another synchronized method of same class, it is safe to execute as it already has lock on this object.
For example:
1 2 3 4 5 6 7 8 9 10 |
public synchronized void method1() { method2(); // some code } public synchronized void method2() { // some code } |
You are actually doing this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public void method1() { synchronized (this) { method2(); // some code } } public void method2() { synchronized (this) { // some code } } |
Here if any thread calls method2 from method1, it will already have lock on this object hence It is safe to execute.
22. What is deadlock?
Answer:
Deadlock is a situation where two or more threads are waiting for each other to release the resource.
23. What are differences between notify and notifyall?
Answer:Â
You can go through difference between notify() and notifyall() to see the differences.
24. What is use of volatile keyword in java?
Answer:Â
If you make any variable volatile
, then this variable will be read from main memory rather then CPU cache, so that each thread will get updated value of the variable.
25. You have started 3 threads and you ought to be certain that main thread finish last. How will you get it done?
Answer:Â
You can use thread’s join()
method to attain this scenario.
Let’s see with the help of example:
Without join() method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package org.arpit.java2blog; class MyRunnable implements Runnable{ @Override public void run() { System.out.println("Current executing thread: "+Thread.currentThread().getName()); } public static void main(String[] args) { MyRunnable runnable=new MyRunnable(); Thread thread1=new Thread(runnable,"Thread1"); Thread thread2=new Thread(runnable,"Thread2"); Thread thread3=new Thread(runnable,"Thread3"); thread1.start(); thread2.start(); thread3.start(); System.out.println("Exiting main thread"); } } |
Output:
Current executing thread: Thread2
Current executing thread: Thread1
Current executing thread: Thread3
As you can see, main thread exited first here.
With join() method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package org.arpit.java2blog; class MyRunnable implements Runnable{ @Override public void run() { System.out.println("Current executing thread: "+Thread.currentThread().getName()); } public static void main(String[] args) { MyRunnable runnable=new MyRunnable(); Thread thread1=new Thread(runnable,"Thread1"); Thread thread2=new Thread(runnable,"Thread2"); Thread thread3=new Thread(runnable,"Thread3"); thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); thread2.join(); thread3.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Exiting main thread"); } } |
Output:
Current executing thread: Thread2
Current executing thread: Thread1
Exiting main thread
As you can see, main thread exited last after calling join()
method on all three threads i.e. thread1
, thread2
and thread3
.
26.How can you print even odd number using 2 threads?
You have been given 2 threads i.e. T1 and T2. You need to print odd numbers using one thread and even numbers using another thread.
For example:
Let’s say you have to Print even odd number using 2 threads upto 10. Here is the sample expected output.
2 T2
3 T1
4 T2
5 T1
6 T2
7 T1
8 T2
9 T1
10 T2
Answer:
Here is the solution using wait and notify in java.
Here is the approach you can use.
- If
num%2==1
, then print using T1 and increment it else T1 will go to wait state. - If
num%2==0
, then print using T2 and increment it else T2 will go to wait state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package org.arpit.java2blog; class PrintOddEven implements Runnable{ public int MAX_NUMBER =10; static int number=1; int rem; static Object lock=new Object(); PrintOddEven(int remainder) { this.rem =remainder; } @Override public void run() { while (number < MAX_NUMBER) { synchronized (lock) { while (number % 2 != rem) { // wait try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " " + number); number++; lock.notifyAll(); } } } } public class OddEvenMain { public static void main(String[] args) { PrintOddEven oddRunnable=new PrintOddEven(1); PrintOddEven evenRunnable=new PrintOddEven(0); Thread t1=new Thread(oddRunnable,"T1"); Thread t2=new Thread(evenRunnable,"T2"); t1.start(); t2.start(); } } |
T2 2
T1 3
T2 4
T1 5
T2 6
T1 7
T2 8
T1 9
T2 10
27. What is ThreadLocal in java?
Answer:
TheadLocal helps you to create variable that can be read and write only by that thread. Two threads can not see each other’s ThreadLocal
variable, so even if they are executing same code, there won’t be any race condition and code will be thread safe.
Here is an example:
Create a ThreadLocalRunnable
which will have ThreadLocal variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package org.arpit.java2blog; public class ThreadLocalRunnable implements Runnable { // ThreadLocal of Integer type private ThreadLocal<Integer> tl = new ThreadLocal<Integer>(); @Override public void run() { tl.set( (int) (Math.random() * 10) ); try { Thread.sleep(1000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName()+":"+tl.get()); } } |
Create main class named ThreadLocalMain
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package org.arpit.java2blog; public class ThreadLocalMain { public static void main(String[] args) throws InterruptedException { ThreadLocalRunnable tl = new ThreadLocalRunnable(); Thread t1 = new Thread(tl,"Thread1"); Thread t2 = new Thread(tl,"Thread2"); t1.start(); t2.start(); t1.join(); t2.join(); } } |
Output:
Thread1:7
As you can see, Thread1
and Thread2
shares same instance of ThreadLocalRunnable
and both set different values for ThreadLocal variable. If we have used synchronized rather than ThreadLocal, later executing thread would have overridden value set by first thread.
28. What is Thread dump?
Answer:
A thread dump is snapshot of all the active threads that are part of process. It contains lot of information about thread and its current state.
A thread dump is very useful when you want to analyze any issue related to deadlock.
You can use jdk tools such as jvisualVM
,jstack
and Java Mission control
. These tools are part of JDK installation and very handy to use.
29. What happens if you don’t override run() method of Thread class?
Answer:
If you don’t override run()
method thread class, then nothing will happen.
When you call `run() method of thread class, it calls target.run() method. Here target is instance of Runnable. When you directly create Thread using default constructor, target is set to null.
1 2 3 4 5 6 7 8 |
@Override public void run() { if (target != null) { target.run(); } } |
Let’s see with the help of example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package org.arpit.java2blog; public class MyThread extends Thread { // no run method public static void main(String args[]){ Thread thread1 = new MyThread(); System.out.println("Before thread execution"); thread1.start(); System.out.println("After thread execution"); } } |
Output:
After thread execution
As you can see, nothing happened when we called thread1.start()
.
Java Concurrency Interview questions
30. What is executor framework?
Answer:
Java 5 has introduced new framework named executor
framework for managing threads.
If you need to create thousands of the threads, your application performance may suffer and also, maintenance of each thread is also overhead. Executor framework solves this problem by limiting number of threads and reusing the same threads once threads had completed its current task.
31. What is Thread pool?
Answer:
Thread pool represents set of worker threads that are waiting for the jobs and these worker threads can be reused many times.
Whenever a task needs to be performance, service provider will pull out a thread out of thread pool to perform the task. If no worker threads are available, then task has to wait for execution.
java.util.concurrent.Executors
class provides factory methods to create the thread pools.
32. Can you list down important factory methods of Executors class?
Answer:
Here are the few important methods of Executors class.
newFixedThreadPool: This method returns a thread pool whose maximum size is fixed. If all threads are busy in execution of tasks and additional tasks are submitted, then they have to wait in queue until any thread is available for executing these tasks.
newCachedThreadPool: This method returns unbounded thread pool. If threads are not used for certain defined time (keepAliveTime
), then it will kill extra threads.
newSingleThreadedExecutor: This method returns an Executor with single thread.
newScheduledThreadPool: This method returns thread pool with fixed size, that can schedule task periodically or with given delay.
33. Can you write a code to implement newFixedThreadPool?
Answer:
You need to use Executors.newFixedThreadPool(numberOfThreads)
to create newFixedThreadPool.
1 2 3 |
ExecutorService executorService=Executors.newFixedThreadPool(noOfThreads); |
Let’s create very simple example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package org.arpit.java2blog; public class RunnableTask implements Runnable { private String taskName; public RunnableTask(String taskName) { super(); this.taskName = taskName; } @Override public void run() { System.out.println("Starting "+ taskName); for (int i = 1; i <= 3; i++) { System.out.println("Executing "+ taskName +" with "+Thread.currentThread().getName()+"====>"+i); } System.out.println("Finishing "+ taskName); } } |
Create main class FixedThreadPoolMain.java
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package org.arpit.java2blog; public class ThreadLocalRunnable implements Runnable { // ThreadLocal of Integer type private ThreadLocal<Integer> tl = new ThreadLocal<Integer>(); @Override public void run() { tl.set( (int) (Math.random() * 10) ); try { Thread.sleep(1000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName()+":"+tl.get()); } } |
Output:
Starting RunnableTask 2
Starting RunnableTask 3
Executing RunnableTask 2 with pool-1-thread-2====>1
Executing RunnableTask 1 with pool-1-thread-1====>1
Executing RunnableTask 3 with pool-1-thread-3====>1
Executing RunnableTask 1 with pool-1-thread-1====>2
Executing RunnableTask 2 with pool-1-thread-2====>2
Executing RunnableTask 1 with pool-1-thread-1====>3
Executing RunnableTask 3 with pool-1-thread-3====>2
Executing RunnableTask 2 with pool-1-thread-2====>3
Executing RunnableTask 3 with pool-1-thread-3====>3
Finishing RunnableTask 1
Finishing RunnableTask 2
Finishing RunnableTask 3
Starting RunnableTask 4
Executing RunnableTask 4 with pool-1-thread-3====>1
Executing RunnableTask 4 with pool-1-thread-3====>2
Executing RunnableTask 4 with pool-1-thread-3====>3
Finishing RunnableTask 4
Starting RunnableTask 5
Executing RunnableTask 5 with pool-1-thread-3====>1
Executing RunnableTask 5 with pool-1-thread-3====>2
Executing RunnableTask 5 with pool-1-thread-3====>3
Finishing RunnableTask 5
As you can notice in the preceding output, first 3 tasks started executed immediately as we have maximum 3 threads in newFixedThreadPool
. Once these 3 tasks are finished, then RunnableTask 4
and RunnableTask 5
got executed.
34. What is BlockingQueue
Answer:
BlockingQueue is special type of queue which is used when producer threads produce object and consumer threads consume object.
Producer thread keeps inserting objects in the queue unless it is full and once it is full, it will be blocked unless consumer threads start consuming.
Similarly, consumer thread keep consuming objects until it is empty. Once it is empty, it will be blocked unless producer threads start producing.
Here are two important methods of BlockingQueue.
put()
: This method to put objects in queue until queue is full and waits for consumer thread to take object after that.
take()
: This method is used to take objects from the queue until it becomes empty. Once it is empty, it waits for producer threads to start producing the objects and put into the queue.
Let’s see simple example of BlockingQueue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package org.arpit.java2blog; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueuePCExample { public static void main(String[] args) { BlockingQueue<String> queue=new ArrayBlockingQueue<>(5); Producer producer=new Producer(queue); Consumer consumer=new Consumer(queue); Thread producerThread = new Thread(producer); Thread consumerThread = new Thread(consumer); producerThread.start(); consumerThread.start(); } static class Producer implements Runnable { BlockingQueue<String> queue=null; public Producer(BlockingQueue queue) { super(); this.queue = queue; } @Override public void run() { try { System.out.println("Producing element 1"); queue.put("Element 1"); Thread.sleep(1000); System.out.println("Producing element 2"); queue.put("Element 2"); Thread.sleep(1000); System.out.println("Producing element 3"); queue.put("Element 3"); } catch (InterruptedException e) { e.printStackTrace(); } } } static class Consumer implements Runnable { BlockingQueue<String> queue=null; public Consumer(BlockingQueue queue) { super(); this.queue = queue; } @Override public void run() { while(true) { try { System.out.println("Consumed "+queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } } } } |
Output:
Consumed Element 1
Producing element 2
Consumed Element 2
Producing element 3
Consumed Element 3
35. What are difference between Runnable and Callable interface in java
Refer: Difference between Runnable and Callable in java
36. What is Lock interface? What are its advantages over synchronized block?
java.util.concurrent.lock.Lock
is introduced in java 1.5 and it provides important operation for blocking.
It is more flexible and convenient synchronization aid than standard synchronized block.
Advantages of Locks are:
- Lock supports fairness which can not be achieved in case of synchronized block. We can specify fairness property to make sure longest waiting thread get fair chance for execution.
- We can use Lock interface’s
lock()
andunlock()
operation in different methods. - We can use
tryLock()
method if we don’t want to block the thread.tryLock()
method attempts to Lock immediately and return true if the locking succeeds. - We can use
lockInterruptibly()
method to interrupt the thread which is waiting for the lock.
37. What is Condition interface?
A Condition
instance is intrinsically bound to a lock. You can use newCondtion()
method of Lock interface to obtain Condition instance.
Condition
is useful when you want to create multiple wait-sets per lock.
For example:
In producer consumer problem, if buffer is full, then producer can wait on one Condition instance notEmpty
and if buffer is empty, then consumer can wait on another Condition instance notFull
unless elements are available.
In case, spaces become available in buffer, consumer can signal producer using Condition instance notEmpty
. Similarly, when producer starts adding elements to buffer, it can signal consumer on Condition instance notFull
.
38. Implement custom BlockingQueue using Lock and Condition?
Answer:
Here is the implementation of custom BlockingQueue using Lock and Condition.
- Use array to store elements in BlockingQueue. Size of array will define maximum capacity of the Blocking Queue.
- Create one lock and two conditions objects:
notFull
andnotEmpty
. - If Queue is full, then producer has to wait on
notFull
condition object - If Queue is empty, then consumer has to wait on
notEmpty
condition object - Create two threads
producer
andconsumer
which will share same CustomBlockingQueue object
Create a class named CustomBlockingQueue.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
package org.arpit.java2blog.entry; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class CustomBlockingQueue { final Lock lock = new ReentrantLock(); // Conditions final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); // Array to store element for CustomBlockingQueue final Object[] arr = new Object[3]; int putIndex, takeIndex; int count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == arr.length){ // Queue is full, producers need to wait notFull.await(); } arr[putIndex] = x; System.out.println("Putting in Queue - " + x); putIndex++; if (putIndex == arr.length){ putIndex = 0; } // Increment the count for the array ++count; // Send signal to consumer notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0){ // Queue is empty, consumers need to wait notEmpty.await(); } Object x = arr[takeIndex]; System.out.println("Taking from queue - " + x); takeIndex++; if (takeIndex == arr.length){ takeIndex = 0; } // reduce the count for the array --count; // send signal producer notFull.signal(); return x; } finally { lock.unlock(); } } } |
Create main class CustomBlockingQueueMain.java
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package org.arpit.java2blog.entry; public class CustomBlockingQueueMain { public static void main(String[] args) { CustomBlockingQueue customBlockingQueue = new CustomBlockingQueue(); // Creating producer and consumer threads Thread producer = new Thread(new Producer(customBlockingQueue)); Thread consumer = new Thread(new Consumer(customBlockingQueue)); producer.start(); consumer.start(); } } class Producer implements Runnable { private CustomBlockingQueue cbq; public Producer(CustomBlockingQueue cbq){ this.cbq = cbq; } @Override public void run() { for (int i = 1; i <= 5; i++) { try { cbq.put(i); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable { private CustomBlockingQueue cbq; public Consumer(CustomBlockingQueue cbq){ this.cbq = cbq; } @Override public void run() { for (int i = 1; i <= 5; i++) { try { cbq.take(); } catch (InterruptedException e) { e.printStackTrace(); } } } } |
Output:
Putting in Queue – 2
Putting in Queue – 3
Taking from queue – 1
Taking from queue – 2
Taking from queue – 3
Putting in Queue – 4
Putting in Queue – 5
Taking from queue – 4
Taking from queue – 5
As you can see in the output, Producer thread got blocked after putting 3 elements in CustomBlockingQueue as array size was given as 3
.
39. What is CountDownLatch?
CountDownLatch is synchronization aid that allows one or more threads to wait until specified operations in other threads complete.
CountDownLatch
is initialized by count. Whenever a thread calls latch.awaits()
where latch is instance of CountDownLatch
, so it will wait until count becomes zero or thread is interrupted by another thread.
So when other threads call latch.countDown()
, count is reduced by 1. Once count reaches 0, thread which called latch.await()
will be resumed.
40. What is CyclicBarrier?
CyclicBarrier is similar to CountDownLatch, but you can reuse once count reaches to 0.
You can also trigger common event once count reaches to 0 in case of CyclicBarrier.
41. What is Semaphore?
When we want to limit number of concurrent threads accessing any resources, we can use Semaphore.
Semaphore maintains set of permits, if permits are not available, thread has to wait.
Semaphores can be used to implement resource pools or bounded collection.
Let’s implement binary semaphore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package org.arpit.java2blog.entry; import java.util.concurrent.Semaphore; public class SemaphoreExampleMain { // Creating semaphore with 1 permit static Semaphore semaphore = new Semaphore(1); static class MyThread extends Thread { String name; //constructor of the MyThread class MyThread(String name) { this.name = name; } public void run() { try { System.out.println(name+" : Getting lock"); System.out.println(name + " : Available Semaphore permits is: "+ semaphore.availablePermits()); semaphore.acquire(); System.out.println(name + " : acquired the lock"); try { for (int i = 1; i <= 5; i++) { System.out.println(name + " : is performing task " + i+ ", available Semaphore permits : "+ semaphore.availablePermits()); //sleep 2 second Thread.sleep(2000); } } finally { System.out.println(name + " : releasing lock..."); // release the permit using release() method semaphore.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } //main method public static void main(String[] args) { System.out.println("Total available Semaphore permits is: "+ semaphore.availablePermits()); //creating 2 threads namely Thread 1 and Thread 2 MyThread thread1 = new MyThread("Thread 1"); //staring thread 1 thread1.start(); MyThread thread2 = new MyThread("Thread 2"); //staring thread 2 thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Total available Semaphore permits is: "+ semaphore.availablePermits()); } } |
Output:
Thread 2 : Getting lock
Thread 1 : Getting lock
Thread 2 : Available Semaphore permits is: 1
Thread 1 : Available Semaphore permits is: 1
Thread 1 : acquired the lock
Thread 1 : is performing task 1, available Semaphore permits : 0
Thread 1 : is performing task 2, available Semaphore permits : 0
Thread 1 : is performing task 3, available Semaphore permits : 0
Thread 1 : is performing task 4, available Semaphore permits : 0
Thread 1 : is performing task 5, available Semaphore permits : 0
Thread 1 : releasing lock…
Thread 2 : acquired the lock
Thread 2 : is performing task 1, available Semaphore permits : 0
Thread 2 : is performing task 2, available Semaphore permits : 0
Thread 2 : is performing task 3, available Semaphore permits : 0
Thread 2 : is performing task 4, available Semaphore permits : 0
Thread 2 : is performing task 5, available Semaphore permits : 0
Thread 2 : releasing lock…
Total available Semaphore permits is: 1
If you notice the output, once the Thread 1
acquired lock, Thread 2
was waiting for permit to be available again. Once Thread 1
released the lock, Thread 2
got the permit and executed the task.
Once Thread 2
released the lock, total available permits again became 1
as expected.
That’s all about multithreading interview questions in java.
You may also like:
- Core java interview questions
- Java Collections interview questions
- Java String interview questions
- OOPs interview questions in java
- Exceptional handling interview questions in java
- Java Serialization interview questions in java
- Method overloading and overriding interview questions
- web services interview questions
- restful web services interview questions
- Data structure and algorithm Interview Questions
- Spring interview questions
- Hibernate interview questions
You may also like: