What is multithreading in Java with example interview questions?
Multithreading in Java
Multithreading in Java allows multiple threads to run concurrently, which is useful for performing multiple tasks simultaneously or in parallel. Each thread runs independently, and they share the same memory space. This is especially important in modern computing, where multi-core processors are common, allowing the application to perform many tasks in parallel and improve performance.
Java provides built-in support for multithreading through the Thread
class and Runnable
interface, which makes it easier to create and manage threads.
How Multithreading Works in Java
- Thread: A thread is a lightweight process that has its own execution path but shares the same memory space with other threads. Java provides the
Thread
class to represent a thread. - Runnable Interface: Another way to implement multithreading is by implementing the
Runnable
interface. This is often preferred over extending theThread
class, as it allows better flexibility and is more suitable for implementing multithreaded tasks in a clean and efficient manner. - Executor Framework: Java also provides a higher-level framework for managing threads called the
Executor
framework, which decouples task submission from the details of how each task will be executed.
Example of Multithreading Using Thread
Class
// Create a class that extends Thread class MyThread extends Thread { public void run() { System.out.println("Thread is running: " + Thread.currentThread().getName()); } } public class Main { public static void main(String[] args) { // Create and start threads MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); thread1.start(); // Starts thread1 thread2.start(); // Starts thread2 } }
Example of Multithreading Using Runnable
Interface
// Create a class that implements Runnable class MyRunnable implements Runnable { public void run() { System.out.println("Runnable thread is running: " + Thread.currentThread().getName()); } } public class Main { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread1 = new Thread(myRunnable); // Create thread using Runnable Thread thread2 = new Thread(myRunnable); thread1.start(); // Starts thread1 thread2.start(); // Starts thread2 } }
Example of Using the ExecutorService
for Thread Management
import java.util.concurrent.*; public class ExecutorServiceExample { public static void main(String[] args) throws InterruptedException, ExecutionException { // Create a thread pool ExecutorService executorService = Executors.newFixedThreadPool(2); // Submit a task (Runnable) to the thread pool executorService.submit(() -> { System.out.println("Task 1 is running: " + Thread.currentThread().getName()); }); executorService.submit(() -> { System.out.println("Task 2 is running: " + Thread.currentThread().getName()); }); // Shut down the executor executorService.shutdown(); } }
Key Points About Multithreading in Java
- Concurrency: Multiple threads are running in parallel, and the operating system manages the scheduling.
- Thread Lifecycle: A thread can be in one of several states:
New
,Runnable
,Blocked
,Waiting
,Timed Waiting
, andTerminated
. - Synchronization: When multiple threads access shared resources, synchronization is necessary to prevent conflicts. This can be achieved using the
synchronized
keyword or more advanced synchronization mechanisms likeReentrantLock
. - Thread Safety: Ensuring that shared resources are accessed by only one thread at a time to avoid corruption of data.
Common Interview Questions on Multithreading in Java
-
What is multithreading in Java, and how is it different from multiprocessing?
- Answer: Multithreading in Java refers to the ability of a CPU to execute multiple threads concurrently within the same process, while multiprocessing involves multiple processes running independently on different CPUs or cores. In multithreading, threads share the same memory space, whereas in multiprocessing, each process has its own memory space.
-
What is the difference between
Thread
andRunnable
in Java?- Answer:
Thread
is a class, andRunnable
is an interface. When usingThread
, you extend the class and override therun()
method. WithRunnable
, you implement therun()
method and pass it to aThread
object. UsingRunnable
is more flexible because it allows you to implement multiple interfaces, whileThread
restricts you to extending theThread
class.
- Answer:
-
What are some advantages of using
ExecutorService
over directly usingThread
?- Answer:
ExecutorService
provides a higher-level abstraction for managing thread execution. It decouples task submission from thread management, provides thread pooling, better management of resources, and offers advanced features likeshutdown()
,submit()
, and handling of results withFuture
. It improves scalability and reduces the complexity of managing threads manually.
- Answer:
-
How do you ensure thread safety in Java?
- Answer: Thread safety can be ensured by using synchronization mechanisms such as:
- The
synchronized
keyword to ensure that only one thread can execute a method or block at a time. ReentrantLock
for more flexible locking mechanisms.volatile
keyword to ensure that a variable is read from and written to the main memory, avoiding caching issues.- Concurrent collections like
ConcurrentHashMap
andCopyOnWriteArrayList
for thread-safe data structures.
- The
- Answer: Thread safety can be ensured by using synchronization mechanisms such as:
-
Explain the thread lifecycle in Java.
- Answer: A thread in Java goes through several states during its lifecycle:
- New: A thread is created but not yet started.
- Runnable: A thread is ready to run but waiting for the CPU time.
- Blocked: A thread is waiting for a lock to be released.
- Waiting: A thread is waiting indefinitely for another thread to perform a particular action.
- Timed Waiting: A thread is waiting for a specific amount of time.
- Terminated: A thread has completed execution.
- Answer: A thread in Java goes through several states during its lifecycle:
-
What is the difference between
wait()
andsleep()
in Java?- Answer:
wait()
is used in synchronization blocks or methods and causes the current thread to release the lock and wait until another thread notifies it.sleep()
makes the current thread pause for a specified time without releasing the lock.
- Answer:
-
What is the purpose of the
join()
method in Java?- Answer: The
join()
method allows one thread to wait for another thread to finish its execution. If Thread A callsjoin()
on Thread B, Thread A will wait until Thread B finishes its execution before continuing.
- Answer: The
-
What is a deadlock in Java, and how can it be avoided?
- Answer: A deadlock occurs when two or more threads are blocked forever, waiting for each other to release resources. It can be avoided by following best practices such as acquiring locks in a consistent order, using
ReentrantLock
with timeout, or usingtryLock()
to avoid indefinite waiting.
- Answer: A deadlock occurs when two or more threads are blocked forever, waiting for each other to release resources. It can be avoided by following best practices such as acquiring locks in a consistent order, using
Recommended Courses
To deepen your understanding of multithreading and concurrency in Java, and to prepare for coding interviews, consider exploring the following courses from DesignGurus.io:
- Grokking Multithreading and Concurrency for Coding Interviews
- Grokking Data Structures & Algorithms for Coding Interviews
- Grokking the System Design Interview
These courses provide in-depth coverage of multithreading and concurrency topics, helping you tackle multithreading challenges effectively in your technical interviews.
GET YOUR FREE
Coding Questions Catalog