0% found this document useful (0 votes)
0 views

Java_Multithreading_Interview_Problems

The document outlines key differences between Thread, Runnable, and Callable in Java, emphasizing the use of Callable for tasks that require a return value. It discusses efficient management of concurrent tasks using ExecutorService and various thread pool types, while also addressing the risks of synchronization, such as deadlocks, and strategies to avoid them. Additionally, it explains the volatile keyword's role in visibility across threads and presents methods for implementing a thread-safe counter, including AtomicInteger and LongAdder.

Uploaded by

pbecic
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

Java_Multithreading_Interview_Problems

The document outlines key differences between Thread, Runnable, and Callable in Java, emphasizing the use of Callable for tasks that require a return value. It discusses efficient management of concurrent tasks using ExecutorService and various thread pool types, while also addressing the risks of synchronization, such as deadlocks, and strategies to avoid them. Additionally, it explains the volatile keyword's role in visibility across threads and presents methods for implementing a thread-safe counter, including AtomicInteger and LongAdder.

Uploaded by

pbecic
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 2

Java Multithreading for Strong Senior Developers

What are the differences between Thread, Runnable, and Callable in Java?
 Thread:
 Represents an actual thread of execution.
 Extending Thread class allows overriding run(), but limits inheritance flexibility.
 Runnable:
 Functional interface with run() method, does not return result or throw checked
exceptions.
 Preferred when task doesn’t need to return a value.
 Callable:
 Callable<T> has call() method that returns a value and can throw checked exceptions.
 Often used with ExecutorService and Future for result-bearing tasks.
 Use Callable when result or exception handling is needed.

How would you manage a large number of concurrent tasks efficiently?


 Use thread pools via ExecutorService to manage and reuse threads.
 Avoid creating a new thread per task — it's resource-intensive.
 Common pool types:
 FixedThreadPool — for a stable number of threads.
 CachedThreadPool — grows dynamically, suitable for short-lived tasks.
 ScheduledThreadPool — for delayed or periodic tasks.
 Submission interfaces:
 submit(Callable) for result-bearing tasks.
 execute(Runnable) for fire-and-forget tasks.
 Monitor system resources to tune pool size properly.

What are the risks of using synchronized and how can deadlocks be avoided?
 synchronized blocks or methods ensure mutual exclusion but introduce potential risks:
 Deadlocks: threads waiting on locks held by each other.
 Reduced concurrency and throughput.
 Priority inversion or thread starvation in high-contention scenarios.
 Strategies to avoid deadlocks:
 Always acquire locks in a consistent global order.
 Avoid holding multiple locks at once unless necessary.
 Use tryLock() with timeout (from ReentrantLock) to detect deadlock potential.
 Favor higher-level concurrency utilities when possible (e.g., java.util.concurrent).

How does the volatile keyword work in Java multithreading?


 volatile ensures visibility of changes to variables across threads.
 When a thread writes to a volatile variable:
 The new value is immediately visible to other threads reading that variable.
 volatile does not ensure atomicity:
 i++ is not atomic even if 'i' is volatile.
 Common use cases:
 Flags for stopping threads (e.g., volatile boolean running).
 Read-heavy single-writer scenarios.
 Use Atomic variables or synchronized for compound actions requiring atomicity.

How would you implement a thread-safe counter in Java?


 Options include:
 Using synchronized blocks or methods around increment logic.
 Using java.util.concurrent.atomic.AtomicInteger.
 Using LongAdder for high-concurrency scenarios.
 AtomicInteger:
 Provides lock-free, thread-safe increment/decrement operations.
 Ideal for most cases.
 LongAdder:
 Uses striped counters internally to reduce contention.
 Outperforms AtomicInteger under high contention, but has slightly more memory
overhead.

You might also like