Multithreading Interview Questions
Multithreading Interview Questions
1) What is multithreading?
Multithreading is a process of executing multiple threads simultaneously.
Multithreading is used to obtain the multitasking. It consumes less memory and
gives the fast and efficient performance. Its main advantages are:
More details.
1|Page
4) What do you understand by inter-thread communication?
o The process of communication between synchronized threads is termed as
inter-thread communication.
o Inter-thread communication is used to avoid thread polling in Java.
o The thread is paused running in its critical section, and another thread is
allowed to enter (or lock) in the same critical section to be executed.
o It can be obtained by wait(), notify(), and notifyAll() methods.
2|Page
public final void wait()
1. New: In this state, a Thread class object is created using a new operator, but
the thread is not alive. Thread doesn't start until we call the start() method.
2. Runnable: In this state, the thread is ready to run after calling the start()
method. However, the thread is not yet selected by the thread scheduler.
3. Running: In this state, the thread scheduler picks the thread from the ready
state, and the thread is running.
4. Waiting/Blocked: In this state, a thread is not running but still alive, or it is
waiting for the other thread to finish.
5. Dead/Terminated: A thread is in terminated or dead state when the run()
method exits.
3|Page
9) What is the difference between preemptive scheduling and
time slicing?
Under preemptive scheduling, the highest priority task executes until it enters the
waiting or dead states or a higher priority task comes into existence. Under time
slicing, a task executes for a predefined slice of time and then reenters the pool of
ready tasks. The scheduler then determines which task should execute next, based on
priority and other factors.
However, the primary differences between both the ways are given below:
4|Page
o By extending the Thread class, we cannot extend any other class, as Java does
not allow multiple inheritances while implementing the Runnable interface; we
can also extend other base class(if required).
o By extending the Thread class, each of thread creates the unique object and
associates with it while implementing the Runnable interface; multiple threads
share the same object
o Thread class provides various inbuilt methods such as getPriority(), isAlive and
many more while the Runnable interface provides a single method, i.e., run().
More details.
5|Page
15) Is it possible to start a thread twice?
No, we cannot restart the thread, as once a thread started and executed, it goes to
the Dead state. Therefore, if we try to start a thread twice, it will give a
runtimeException "java.lang.IllegalThreadStateException". Consider the following
example.
Output
ADVERTISING
thread is executing now........
Exception in thread "main"
java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at Multithread1.main(Multithread1.java:13)
More details.
6|Page
other user threads are ended/died. There are two methods for daemon thread
available in the Thread class:
More details.
Output
Running thread is daemon...
Exception in thread "main"
java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
at Testdaemon1.main(Testdaemon1.java:8)
More details.
7|Page
o Shutdown hooks initialized but can only be started when JVM shutdown
occurred.
o Shutdown hooks are more reliable than the finalizer() because there are very
fewer chances that shutdown hooks not run.
o The shutdown hook can be stopped by calling the halt(int) method of Runtime
class.
More details.
When the multiple threads try to do the same task, there is a possibility of an
erroneous result, hence to remove this issue, Java uses the process of
synchronization which allows only one thread to be executed at a time.
Synchronization can be achieved in three ways:
More details.
8|Page
The Synchronized block can be used to perform synchronization on any specific
resource of the method. Only one thread at a time can execute on a particular
resource, and all other threads which attempt to enter the synchronized block are
blocked.
More details.
9|Page
o Avoid Nested lock: Nested lock is the common reason for deadlock as
deadlock occurs when we provide locks to various threads so we should give
one lock to only one thread at some particular time.
o Avoid unnecessary locks: we must avoid the locks which are not required.
o Using thread join: Thread join helps to wait for a thread until another thread
doesn't finish its execution so we can avoid deadlock by maximum use of join
method.
o Synchronization
o Using Volatile keyword
o Using a lock based mechanism
o Use of atomic wrapper classes
10 | P a g e
Volatile keyword is used in multithreaded programming to achieve the thread safety,
as a change in one volatile variable is visible to all other threads so one variable can
be used by one thread at a time.
o Executor
o FarkJoinPool
o ExecutorService
o ScheduledExecutorService
o Future
o TimeUnit(Enum)
o CountDownLatch
o CyclicBarrier
o Semaphore
o ThreadFactory
o BlockingQueue
o DelayQueue
o Locks
o Phaser
11 | P a g e
The Executor Interface provided by the package java.util.concurrent is the simple
interface used to execute the new task. The execute() method of Executor interface is
used to execute some given command. The syntax of the execute() method is given
below.
void execute(Runnable command)
Consider the following example:
1. import java.util.concurrent.Executor;
2. import java.util.concurrent.Executors;
3. import java.util.concurrent.ThreadPoolExecutor;
4. import java.util.concurrent.TimeUnit;
5.
6. public class TestThread {
7. public static void main(final String[] arguments) throws InterruptedExcepti
on {
8. Executor e = Executors.newCachedThreadPool();
9. e.execute(new Thread());
10. ThreadPoolExecutor pool = (ThreadPoolExecutor)e;
11. pool.shutdown();
12. }
13.
14. static class Thread implements Runnable {
15. public void run() {
16. try {
17. Long duration = (long) (Math.random() * 5);
18. System.out.println("Running Thread!");
19. TimeUnit.SECONDS.sleep(duration);
20. System.out.println("Thread Completed");
21. } catch (InterruptedException ex) {
22. ex.printStackTrace();
23. }
24. }
25. }
26. }
Output
Running Thread!
Thread Completed
12 | P a g e
1.
2. import java.util.Random;
3. import java.util.concurrent.ArrayBlockingQueue;
4. import java.util.concurrent.BlockingQueue;
5.
6. public class TestThread {
7.
8. public static void main(final String[] arguments) throws InterruptedExcepti
on {
9. BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10)
;
10.
11. Insert i = new Insert(queue);
12. Retrieve r = new Retrieve(queue);
13.
14. new Thread(i).start();
15. new Thread(r).start();
16.
17. Thread.sleep(2000);
18. }
19.
20.
21. static class Insert implements Runnable {
22. private BlockingQueue<Integer> queue;
23.
24. public Insert(BlockingQueue queue) {
25. this.queue = queue;
26. }
27.
28. @Override
29. public void run() {
30. Random random = new Random();
31.
32. try {
33. int result = random.nextInt(200);
34. Thread.sleep(1000);
35. queue.put(result);
36. System.out.println("Added: " + result);
37.
38. result = random.nextInt(10);
39. Thread.sleep(1000);
40. queue.put(result);
41. System.out.println("Added: " + result);
13 | P a g e
42.
43. result = random.nextInt(50);
44. Thread.sleep(1000);
45. queue.put(result);
46. System.out.println("Added: " + result);
47. } catch (InterruptedException e) {
48. e.printStackTrace();
49. }
50. }
51. }
52.
53. static class Retrieve implements Runnable {
54. private BlockingQueue<Integer> queue;
55.
56. public Retrieve(BlockingQueue queue) {
57. this.queue = queue;
58. }
59.
60. @Override
61. public void run() {
62.
63. try {
64. System.out.println("Removed: " + queue.take());
65. System.out.println("Removed: " + queue.take());
66. System.out.println("Removed: " + queue.take());
67. } catch (InterruptedException e) {
68. e.printStackTrace();
69. }
70. }
71. }
72. }
Output
Added: 96
Removed: 96
Added: 8
Removed: 8
Added: 5
Removed: 5
14 | P a g e
1.
2. import java.util.concurrent.BlockingQueue;
3. import java.util.concurrent.LinkedBlockingQueue;
4. import java.util.logging.Level;
5. import java.util.logging.Logger;
6. public class ProducerConsumerProblem {
7. public static void main(String args[]){
8. //Creating shared object
9. BlockingQueue sharedQueue = new LinkedBlockingQueue();
10.
11. //Creating Producer and Consumer Thread
12. Thread prod = new Thread(new Producer(sharedQueue));
13. Thread cons = new Thread(new Consumer(sharedQueue));
14.
15. //Starting producer and Consumer thread
16. prod.start();
17. cons.start();
18. }
19.
20. }
21.
22. //Producer Class in java
23. class Producer implements Runnable {
24.
25. private final BlockingQueue sharedQueue;
26.
27. public Producer(BlockingQueue sharedQueue) {
28. this.sharedQueue = sharedQueue;
29. }
30.
31. @Override
32. public void run() {
33. for(int i=0; i<10; i++){
34. try {
35. System.out.println("Produced: " + i);
36. sharedQueue.put(i);
37. } catch (InterruptedException ex) {
38. Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null,
ex);
39. }
40. }
41. }
42.
15 | P a g e
43. }
44.
45. //Consumer Class in Java
46. class Consumer implements Runnable{
47.
48. private final BlockingQueue sharedQueue;
49.
50. public Consumer (BlockingQueue sharedQueue) {
51. this.sharedQueue = sharedQueue;
52. }
53.
54. @Override
55. public void run() {
56. while(true){
57. try {
58. System.out.println("Consumed: "+ sharedQueue.take());
59. } catch (InterruptedException ex) {
60. Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null
, ex);
61. }
62. }
63. }
64. }
Output
Produced: 0
Produced: 1
Produced: 2
Produced: 3
Produced: 4
Produced: 5
Produced: 6
Produced: 7
Produced: 8
Produced: 9
Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Consumed: 7
Consumed: 8
Consumed: 9
16 | P a g e
38) What is the difference between Java Callable interface and
Runnable interface?
The Callable interface and Runnable interface both are used by the classes which
wanted to execute with multiple threads. However, there are two main differences
between the both :
o A Callable <V> interface can return a result, whereas the Runnable interface
cannot return any result.
o A Callable <V> interface can throw a checked exception, whereas the
Runnable interface cannot throw checked exception.
o A Callable <V> interface cannot be used before the Java 5 whereas the
Runnable interface can be used.
o Lock interface provides the guarantee of sequence in which the waiting thread
will be given the access, whereas the synchronized block doesn't guarantee it.
o Lock interface provides the option of timeout if the lock is not granted
whereas the synchronized block doesn't provide that.
o The methods of Lock interface, i.e., Lock() and Unlock() can be called in
different methods whereas single synchronized block must be fully contained
in a single method.
17 | P a g e
The ExecutorService Interface is the subinterface of Executor interface and adds the
features to manage the lifecycle. Consider the following example.
1.
2. import java.util.concurrent.ExecutorService;
3. import java.util.concurrent.Executors;
4. import java.util.concurrent.TimeUnit;
5.
6. public class TestThread {
7. public static void main(final String[] arguments) throws InterruptedExcepti
on {
8. ExecutorService e = Executors.newSingleThreadExecutor();
9.
10. try {
11. e.submit(new Thread());
12. System.out.println("Shutdown executor");
13. e.shutdown();
14. e.awaitTermination(5, TimeUnit.SECONDS);
15. } catch (InterruptedException ex) {
16. System.err.println("tasks interrupted");
17. } finally {
18.
19. if (!e.isTerminated()) {
20. System.err.println("cancel non-finished tasks");
21. }
22. e.shutdownNow();
23. System.out.println("shutdown finished");
24. }
25. }
26.
27. static class Task implements Runnable {
28.
29. public void run() {
30.
31. try {
32. Long duration = (long) (Math.random() * 20);
33. System.out.println("Running Task!");
34. TimeUnit.SECONDS.sleep(duration);
35. } catch (InterruptedException ex) {
36. ex.printStackTrace();
37. }
38. }
39. }
18 | P a g e
40. }
Output
Shutdown executor
shutdown finished
19 | P a g e
Java FutureTask class provides a base implementation of the Future interface. The
result can only be obtained if the execution of one task is completed, and if the
computation is not achieved then get method will be blocked. If the execution is
completed, then it cannot be re-started and can't be canceled.
Syntax
public class FutureTask<V> extends Object implements RunnableFuture<V>
20 | P a g e