Introduction of Multithreading in java
Multithreading is a powerful feature in Java that enables efficient CPU usage by allowing multiple threads to run simultaneously. By learning multithreading in Java, developers can optimize code performance and create responsive applications.
What is Multithreading in Java?
Multithreading refers to the ability of a CPU to execute multiple threads concurrently. A thread is the smallest unit of a process, and multithreading allows these units to run independently.
Benefits of Multithreading:
- Improved application performance.
- Better resource utilization.
- Enhanced responsiveness, especially for applications with complex tasks.
Core Concepts of Multithreading
Thread Lifecycle:
- New: The thread is created.
- Runnable: The thread is ready to run.
- Blocked: The thread is blocked and waiting.
- Terminated: The thread has completed execution.
Code Example: Basic Multithreading Structure
public class MyThread extends Thread { public void run() { System.out.println("Thread is running."); } public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // Starts the thread } }
How to Create Threads in Java
Java provides two main ways to implement threads: by extending the Thread
class or implementing the Runnable
interface.
Code Example: Using Runnable
Interface
MyRunnable implements Runnable { public void run() { System.out.println("Runnable thread is running."); } public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
Thread Synchronization in Java
In multithreading, synchronization ensures that two threads do not simultaneously access shared resources, preventing inconsistent data.
Code Example: Synchronized Block
codeclass Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } class SyncExample { public static void main(String[] args) { Counter counter = new Counter(); // Multiple threads incrementing the counter Thread t1 = new Thread(counter::increment); Thread t2 = new Thread(counter::increment); t1.start(); t2.start(); } }
Best Practices for Multithreading in Java
- Minimize Synchronization: Overusing synchronization can cause performance bottlenecks.
- Use Thread Pools: Instead of creating new threads for each task, use a thread pool to manage resources efficiently.
- Avoid Deadlocks: Carefully structure code to prevent threads from blocking each other indefinitely.
Code Example: Using Thread Pools
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { executor.submit(() -> System.out.println("Executing task")); } executor.shutdown(); } }
Common Interview Questions
1. What is the difference between Thread
and Runnable
in Java?
- Asked by: Amazon, Cognizant, IBM
- Answer:
Thread
is a class that represents a thread of execution, whileRunnable
is an interface for defining tasks that can be executed by a thread. ImplementingRunnable
allows for better design and flexibility because it separates the task from the executor. WithRunnable
, you can also extend other classes, as Java doesn’t support multiple inheritance.
2. How do you prevent thread interference in Java?
- Asked by: Oracle, TCS, Wipro
- Answer: Thread interference occurs when multiple threads concurrently modify shared data without proper synchronization. To prevent this, use:
- Synchronized methods or blocks to allow only one thread at a time to access critical sections.
- java.util.concurrent locks and atomic variables (e.g.,
AtomicInteger
) to manage access safely. - Volatile keyword to ensure changes to variables are visible to all threads immediately.
- Thread-safe collections like
ConcurrentHashMap
for shared data structures.
3. Explain deadlock and how to avoid it in Java.
- Asked by: Microsoft, Infosys, SAP
- Answer: Deadlock occurs when two or more threads are waiting on each other’s resources, causing an indefinite block. To avoid deadlock:
- Use a consistent order for locking resources across threads.
- Use timeout-based locking with
tryLock
to avoid indefinite waiting. - Limit the scope of locks by avoiding nested locks and using higher-level constructs like semaphores, or synchronized collections that manage locks internally.
4. What are daemon threads, and how do they differ from regular threads?
- Asked by: Adobe, Google, Cisco
- Answer: Daemon threads are background threads that support user threads and run continuously. Unlike user threads, the JVM does not wait for daemon threads to finish before exiting, so they’re suited for tasks like garbage collection and monitoring. You can set a thread as daemon by using
setDaemon(true)
.
5. What is the purpose of the join()
method in Java, and when would you use it?
- Asked by: Accenture, LinkedIn, Facebook
- Answer: The
join()
method makes one thread wait for another to complete. For example, if Thread A callsthreadB.join()
, Thread A will pause execution until Thread B finishes. This is useful when a thread’s task depends on another thread’s completion, or when you need to maintain a specific sequence of task executions.
Practice Exercises
- Create a program that uses threads to perform multiple calculations.
- Implement a synchronized counter that can be accessed by multiple threads.
Additional Resources
- Java Thread Documentation
- Java Concurrency in Practice by Brian Goetz
PLAY WITH JAVA..!!
Question
Your answer:
Correct answer:
Your Answers