Java interview – Concurrency

 

1. Why is there a need for multi-threading?

Multi-threading allows your program to execute logic in parallel. For example: if you are tasked to develop an API endpoint to download a file, read from the database, run calculations, call another API, then this will be an expensive task in terms of resources and time.

  • STEP-I: Read from DB => 10 milliseconds
  • STEP-II: Run calculations => 20 milliseconds
  • STEP-III: Download a file from AWS S3 => 3 seconds
  • STEP-IV: Call Stripe API to get user’s credit card info => 2 seconds

As you can see, it will take 5+ seconds with the best-case scenario. This isn’t too bad but still, users expect a faster response than 5+ seconds. If we use multi-threading to execute these steps in parallel then we can decrease the response time significantly.

  • STEP-I: Read from DB => 10 milliseconds
  • STEP-II: Run calculations, Download a file from AWS S3, Call Stripe API to get user’s credit card info => 3 seconds

Now instead of 5+ seconds, our new response time is 3 seconds.

2. What is multi-threading?

Multi-threading is executing a series of logic in parallel. Example: a web server is using multi-threading to execute multiple requests from clients(web browsers or mobile apps) at the same time.

3. What is a thread?

A thread is an independent path of execution within a program. Many threads can run concurrently within a program, either asynchronously or synchronously.

4. What are the differences between a thread and a process?

Threads share memory among themselves. A process does not share memory.

Threads are lightweight compared to processes.

Context switching between threads is usually less expensive than between processes.

The cost of thread intercommunication is relatively low compared to that of process intercommunication.

Threads allow different tasks to be performed concurrently.

Java Multithreading

Process Vs Threads

5. How can you create a thread?

There are two ways you can create a thread. You can extend the Thread class or implement the Runnable interface. Implementing the Runnable interface is preferred by many because it allows you to implement other interfaces or extend another class.

Using the Thread class

public class MemberThread extends Thread {

	@Override
	public void run() {
		super.run();
                // coding to execute
		System.out.println("run MemberThread...");
	}
}

Using the Runnable interface

public class UserRunnable implements Runnable {

	public UserRunnable() {
		super();
		System.out.println("UserRunnable");
	}

	@Override
	public void run() {
                // code to execute
		System.out.println("running UserRunnable..");
	}
}

 

public class ThreadCreationDemo {

	public static void main(String[] args) {
		Thread userThread = new Thread(new UserRunnable());
		userThread.start();
		
		MemberThread memberThread = new MemberThread();
		memberThread.start();
	}

}

Result

UserRunnable
running UserRunnable..
start MemberThread...
run MemberThread...

6. What are the different statuses of a thread?

a. NEW – a new Thread instance that was not yet started via Thread.start().

b. 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.

c. RUNNING – In this state, the thread scheduler picks the thread from the ready state, and the thread is running.

c. 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.

d. 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.

e. 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.

f. TERMINATED – a thread has completed the execution of its Runnable.run() method and terminated.

The state of a Thread can be checked using the Thread.getState() method.

Java thread life cycle

Thread Life cycle in java, Thread States in java, thread life cycle

7. What is the difference between the Runnable interface and the Callable interface?

The Runnable interface does not have a return value or to throw unchecked exceptions.

The Callable interface has a return 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.

FutureTask<Integer> futureTask = new FutureTask<Integer>(new CustomerCallable());

Thread customerCallableStart = new Thread(futureTask);
customerCallableStart.start();

try {
	int result = futureTask.get();
	System.out.println("result: " + result);
} catch (InterruptedException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
} catch (ExecutionException e) {
	// TODO Auto-generated catch block
        e.printStackTrace();
}

8. What is context-switching?

In Context switching, the state of the thread or process is stored so that it can be restored and execution can be resumed from the same point later. Context switching enables multiple threads or processes to share the same CPU.

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.

10. What is the difference between the start() method and the run() method?

The start() method is used to start a newly created thread, while start() internally calls run() method.

When you invoke run() directly, the execution will run on the main thread. It won’t create a new thread for you.

11. What is the difference between user threads and daemon threads?

When we create a Thread in java program, it’s known as user thread. A daemon thread runs in the background and doesn’t prevent JVM from terminating. When there are no user threads running, JVM shutdown the program and quits. A child thread created from daemon thread is also a daemon thread.

12. How can we pause the execution of a Thread for a specific time?

We can use the Thread class sleep() method to pause the execution of a thread for a duration of time. Note that this will not stop the processing of the thread, once the thread is awake from sleep, it states gets changed to runnable and based on thread scheduling, it gets executed.

13. What do you understand about Thread Priority?

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

14. How can we make sure that the main thread is the last thread to finish in Java Program?

We can use Thread join() method to make sure all the threads created by the program is dead before finishing the main function

15. How does thread communicate with each other?

When threads share resources, communication between Threads is important to coordinate their efforts. Object class wait(), notify() and notifyAll() methods allow threads to communicate about the lock status of a resource.

16. What is the difference between wait() and sleep() method?

The wait() method releases the lock but the sleep() method doesn’t.

The wait() method is defined in Object class but the sleep() method is from the Thread class.

17. 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 runtime Exception “java.lang.IllegalThreadStateException”.

18. What are daemon threads?

Daemon threads are low priority threads that provide the background support and services to the user threads. Daemon thread gets automatically terminated by the JVM if the program remains with the daemon thread only, and all other user threads are ended/died. We can make a user thread a daemon thread by calling the setDaemon() method. We can only do this before the thread is starting otherwise it will throw an exception. There are two methods for daemon thread available in the Thread class.

  • public void setDaemon(boolean status): It used to mark the thread daemon thread or a user thread.
  • public boolean isDaemon(): It checks the thread is daemon or not.

19. Why Thread sleep() and yield() methods are static?

Thread sleep() and yield() methods work on the currently executing thread. So there is no point in invoking these methods on some other threads that are in a wait state. That’s why these methods are made static so that when this method is called statically, it works on the currently executing thread and avoid confusion to the programmers who might think that they can invoke these methods on some non-running threads.

20. How can we achieve thread-safety in Java?

There are several ways to achieve thread-safety in java – synchronization, atomic concurrent classes, implementing concurrent Lock interface, using the volatile keyword, using immutable classes and Thread-safe classes.

 

21. What is the volatile keyword in Java

It is used to mark a variable as “being stored in main memory”. More precisely that means, that every read of a volatile variable will be read from the computer’s main memory, and not from the CPU cache and that every a write happens to a volatile variable will be written to main memory, and not just to the CPU cache.

A change in a volatile variable is visible to all other threads so one variable can be used by one thread at a time.

In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs.

Threads may hold copies of variables from main memory in CPU caches.


With non-volatile variables, there are no guarantees about when the Java Virtual Machine (JVM) reads data from the main memory into CPU caches or writes data from CPU caches to the main memory. This can cause problems.

Using volatile is sometimes not enough. It is recommended to use synchronized to guarantee that the reading and writing of the variable are atomic.

22. Which way is more preferred – Synchronized method or Synchronized block?

The synchronized block is the more preferred way because it doesn’t lock the Object, synchronized methods lock the Object and if there are multiple synchronization blocks in the class, even though they are not related, it will stop them from execution and put them in wait state to get the lock on Object.

23. Can you synchronize a static method?

Yes, if you do you will be synchronizing the class so only one thread can enter into a synchronized static method.

24. What is Threadlocal?

The Threadlocal class enables you to create variables that can only be read and written by the same thread. Thus, even if two threads are executing the same code, and the code has a reference to the same Threadlocal variable, the two threads cannot see each other’s Threadlocal variables.

If we want to use an ExecutorService and submit a Runnable to it, using ThreadLocal will yield non-deterministic results – because we do not have a guarantee that every Runnable action for a given userId will be handled by the same thread every time it is executed.

Use it when you have some object that is not thread-safe, but you want to avoid synchronizing access to that object.

public class UserThreadLocal extends Thread {

	private static final AtomicInteger id = new AtomicInteger(0);

	ThreadLocal<String> privateName = ThreadLocal.withInitial(() -> " John--" + id.incrementAndGet());

	@Override
	public void run() {
		super.run();
		System.out.println("run..." + privateName.get());
	}
}

25. What is Java Thread Dump, How can we get Java Thread dump of a Program?

A thread dump is a list of all the threads active in the JVM, thread dumps are very helpful in analyzing bottlenecks in the application and analyzing deadlock situations. There are many ways using which we can generate Thread dump – Using Profiler, Kill -3 command, jstack tool, etc. I prefer jstack tool to generate thread dump of a program because it’s easy to use and comes with JDK installation. Since it’s a terminal-based tool, we can create a script to generate thread dump at regular intervals to analyze it later on.

26. 30 commonly asked interview questions related to Java concurrency

  1. Question: What is concurrency in Java? Answer: Concurrency is the ability of a program to execute multiple tasks concurrently. It allows for efficient utilization of system resources and improved program performance.

  2. Question: What is a thread in Java? Answer: A thread is a lightweight unit of execution within a program. It allows multiple parts of a program to execute concurrently.

  3. Question: How can you create a thread in Java? Answer: There are two ways to create a thread in Java: by extending the Thread class or by implementing the Runnable interface.

  4. Question: What is the difference between the start() and run() methods of a thread? Answer: The start() method is used to start a new thread and internally calls the run() method, which contains the code that will be executed by the thread.

  5. Question: What is thread synchronization? Answer: Thread synchronization is the coordination of multiple threads to ensure their safe and orderly execution. It is used to prevent race conditions and ensure data consistency.

  6. Question: How can you synchronize a block of code in Java? Answer: You can use the synchronized keyword to synchronize a block of code by enclosing it within a synchronized block or by declaring a synchronized method.

  7. Question: What is the purpose of the volatile keyword in Java? Answer: The volatile keyword is used to declare a variable whose value may be modified by multiple threads. It ensures that changes to the variable are immediately visible to other threads.

  8. Question: What is a race condition? Answer: A race condition occurs when multiple threads access and modify shared data concurrently, leading to unpredictable results. It can be resolved using synchronization mechanisms.

  9. Question: What are the differences between wait() and sleep() methods in Java? Answer: The wait() method is used for inter-thread communication, allowing a thread to wait until another thread notifies it. The sleep() method is used to pause the execution of a thread for a specified amount of time.

  10. Question: What is a deadlock? Answer: A deadlock occurs when two or more threads are blocked forever, each waiting for a resource that the other thread holds. Deadlocks can be avoided by careful resource allocation and proper synchronization.

  11. Question: Explain the concept of thread pooling. Answer: Thread pooling involves creating a pool of reusable threads to execute tasks. It reduces the overhead of creating and destroying threads for each task, resulting in improved performance.

  12. Question: What is the Executor framework in Java? Answer: The Executor framework provides a higher-level abstraction for managing and executing threads. It decouples task submission from execution policies.

  13. Question: What is the purpose of the Callable interface in Java? Answer: The Callable interface is similar to the Runnable interface, but it can return a result and throw checked exceptions. It is used with the ExecutorService to execute tasks and retrieve results.

  14. Question: What is the Java Memory Model (JMM)? Answer: The Java Memory Model defines the rules and guarantees for the interaction of threads and memory. It ensures visibility and ordering of memory operations across multiple threads.

  15. Question: Explain the concept of atomic operations in Java. Answer: Atomic operations are indivisible operations that are performed as a single unit of execution. They ensure that operations on shared data are thread-safe and free from race conditions.

  16. Question: What is a semaphore in Java concurrency? Answer: A semaphore is a synchronization primitive that controls access to a shared resource. It allows aContinuing from the previous response, here are more Java concurrency interview questions along with their answers:

  17. Question: What is the purpose of the CountDownLatch class in Java? Answer: The CountDownLatch class is used to synchronize threads by allowing them to wait until a certain number of operations or events have occurred before proceeding.

  18. Question: What is the purpose of the CyclicBarrier class in Java? Answer: The CyclicBarrier class is used to synchronize multiple threads by making them wait at a barrier until all threads have reached it. Once all threads have arrived, they can proceed simultaneously.

  19. Question: What is the purpose of the ReentrantLock class in Java? Answer: The ReentrantLock class provides a more advanced locking mechanism than the synchronized keyword. It allows for finer-grained control over locking and supports features like fairness and interruptible locks.

  20. Question: What is the purpose of the ReadWriteLock interface in Java? Answer: The ReadWriteLock interface provides a way to have multiple threads simultaneously read from a shared resource, while only allowing one thread to write to it at a time. It improves concurrency in scenarios with frequent reads and infrequent writes.

  21. Question: What is the purpose of the BlockingQueue interface in Java? Answer: The BlockingQueue interface provides a thread-safe queue implementation that supports blocking operations, such as waiting for elements to become available or waiting for space to become available for adding elements.

  22. Question: What is the purpose of the ThreadLocal class in Java? Answer: The ThreadLocal class provides a way to create thread-local variables, where each thread has its own copy of the variable. It is useful for maintaining thread-specific data.

  23. Question: What is the purpose of the volatile keyword in relation to multi-threading? Answer: The volatile keyword ensures that a variable’s value is always read from and written to main memory, rather than being cached in a thread’s local cache. It guarantees visibility of the variable’s latest value across multiple threads.

  24. Question: What is the purpose of the join() method in Java? Answer: The join() method is used to make a calling thread wait until a target thread completes its execution. It is often used to ensure that the main thread waits for all worker threads to finish before proceeding.

  25. Question: What is the purpose of the notify() and notifyAll() methods in Java? Answer: The notify() method is used to wake up a single thread that is waiting on the same object’s monitor, while the notifyAll() method wakes up all threads waiting on the object’s monitor. These methods are used for inter-thread communication.

  26. Question: Explain the concept of thread starvation and how it can be avoided. Answer: Thread starvation occurs when a thread is perpetually denied access to the CPU or resources it needs. It can be avoided by implementing proper thread scheduling, fairness policies, and resource management.

  27. Question: Explain the concept of thread starvation and how it can be avoided. Answer: Thread starvation occurs when a thread is perpetually denied access to the CPU or resources it needs. It can be avoided by implementing proper thread scheduling, fairness policies, and resource management.

  28. Question: What is the purpose of the ForkJoinPool class in Java? Answer: The ForkJoinPool class is used for parallelizing tasks that can be divided into subtasks and executed concurrently. It is based on the divide-and-conContinuing from the previous response, here are more Java concurrency interview questions along with their answers:

  29. Question: What is the purpose of the CompletableFuture class in Java? Answer: The CompletableFuture class provides a way to handle asynchronous computations and compose them in a non-blocking manner. It allows for chaining and combining asynchronous operations.

  30. Question: Explain the concept of non-blocking and asynchronous programming in Java. Answer: Non-blocking and asynchronous programming techniques allow for concurrent execution of tasks without blocking the calling thread. Non-blocking operations return immediately, and the result is delivered at a later time, often through callbacks or promises.

 

 

 

 

 

 

 




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *