{"id":983,"date":"2025-06-11T10:54:27","date_gmt":"2025-06-11T07:54:27","guid":{"rendered":"https:\/\/www.certbolt.com\/certification\/?p=983"},"modified":"2025-12-30T14:48:04","modified_gmt":"2025-12-30T11:48:04","slug":"java-thread-basics-and-execution-life-cycle","status":"publish","type":"post","link":"https:\/\/www.certbolt.com\/certification\/java-thread-basics-and-execution-life-cycle\/","title":{"rendered":"Java Thread Basics and Execution Life Cycle"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">A thread in Java is the smallest unit of execution within a program. Every Java application starts with a single thread, known as the main thread, which is initiated by the Java Virtual Machine (JVM) at the start of program execution. The main thread begins by invoking the main() method, from which the program&#8217;s operations commence.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In Java, a thread represents a separate path of execution. Java programs can utilize multiple threads to execute tasks concurrently, allowing for more efficient use of system resources. Each thread can operate independently while sharing the same memory space, which facilitates efficient communication and data sharing between threads. Threads are scheduled based on priority, and higher-priority threads are generally executed before lower-priority ones.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Threads in Java are essential for managing multiple tasks within the same program, such as performing computations while maintaining a responsive user interface or handling multiple client requests in server-side applications. Each thread maintains its own program counter, stack, and local variables, which enables it to execute independently of other threads.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Java threads enable concurrent execution, which is particularly beneficial for tasks like input\/output operations, network communications, and other time-consuming processes. Understanding how to create and manage threads effectively is crucial for building responsive and efficient Java applications.<\/span><\/p>\n<p><b>Creating a Thread in Java<\/b><\/p>\n<p><b>Extending the Thread Class<\/b><\/p>\n<p><span style=\"font-weight: 400;\">One way to create a thread in Java is by extending the <\/span><span style=\"font-weight: 400;\">java.lang.Thread<\/span><span style=\"font-weight: 400;\"> class. This involves defining a new class that inherits from Thread and overriding the <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method to specify the actions the thread should perform.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">class MyThread extends Thread {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void run() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread is running&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0MyThread t1 = new MyThread();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In this example, the <\/span><span style=\"font-weight: 400;\">start()<\/span><span style=\"font-weight: 400;\"> method is used to create and launch a new thread, which then executes the code defined in the <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method.<\/span><\/p>\n<p><b>Implementing the Runnable Interface<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Another way to create a thread in Java is by implementing the <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> interface. This approach involves creating a class that implements <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> and defining the <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method. This method is then passed to a <\/span><span style=\"font-weight: 400;\">Thread<\/span><span style=\"font-weight: 400;\"> object, which starts the thread.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">class MyRunnable implements Runnable {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void run() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread is running using Runnable&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0MyRunnable myRunnable = new MyRunnable();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t1 = new Thread(myRunnable);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Using the <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> interface is considered more flexible since the class can extend another class as well, unlike extending the Thread class, which limits inheritance.<\/span><\/p>\n<p><b>Lifecycle of a Thread in Java<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The lifecycle of a thread in Java represents the various states a thread can be in from creation to termination. These states are managed internally by the JVM and controlled via thread methods and scheduling mechanisms.<\/span><\/p>\n<p><b>New State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">When a thread object is instantiated using the <\/span><span style=\"font-weight: 400;\">Thread<\/span><span style=\"font-weight: 400;\"> class, it is said to be in the New state. At this point, the thread has been created but has not yet started executing. The <\/span><span style=\"font-weight: 400;\">start()<\/span><span style=\"font-weight: 400;\"> method has not been called.<\/span><\/p>\n<p><b>Runnable State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Once the <\/span><span style=\"font-weight: 400;\">start()<\/span><span style=\"font-weight: 400;\"> method is invoked on a thread object, the thread enters the Runnable state. It is now ready to run and is waiting for CPU time to be allocated by the thread scheduler. The thread is in a queue, prepared to execute as soon as it gets access to the CPU.<\/span><\/p>\n<p><b>Running State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A thread transitions to the Running state when it is selected by the thread scheduler from the Runnable queue. In this state, the thread is actively executing the instructions defined in its <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method. The thread will remain in this state until it completes its execution or is moved to a non-runnable state.<\/span><\/p>\n<p><b>Blocked (Non-Runnable) State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A thread enters the Blocked or Non-Runnable state when it is alive but not eligible to run. This can happen when the thread is waiting for a monitor lock or when the <\/span><span style=\"font-weight: 400;\">sleep()<\/span><span style=\"font-weight: 400;\"> or <\/span><span style=\"font-weight: 400;\">wait()<\/span><span style=\"font-weight: 400;\"> methods are called. Although the thread is still active, it cannot be scheduled for execution.<\/span><\/p>\n<p><b>Dead State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A thread reaches the Dead state when it finishes executing its <\/span><span style=\"font-weight: 400;\">run<\/span><span style=\"font-weight: 400;\"> method or when it is explicitly terminated. Once a thread enters this state, it cannot be restarted.<\/span><\/p>\n<p><b>Java Thread Priorities<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Each thread in Java has a priority, which helps determine the order in which threads are scheduled for execution. The priority is an integer ranging from 1 (lowest) to 10 (highest), with 5 as the default priority. Threads with higher priorities are typically given preference by the scheduler.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Thread priorities can be set using the following constants:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Thread.MIN_PRIORITY<\/span><span style=\"font-weight: 400;\"> (1)<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Thread.NORM_PRIORITY<\/span><span style=\"font-weight: 400;\"> (5)<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Thread.MAX_PRIORITY<\/span><span style=\"font-weight: 400;\"> (10)<\/span>&nbsp;<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">class PriorityThread extends Thread {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void run() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Running thread name: &#187; + Thread.currentThread().getName());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Running thread priority: &#187; + Thread.currentThread().getPriority());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PriorityThread t1 = new PriorityThread();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PriorityThread t2 = new PriorityThread();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.setPriority(Thread.MIN_PRIORITY);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t2.setPriority(Thread.MAX_PRIORITY);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t2.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">By adjusting thread priorities, developers can influence the order of thread execution, though exact behavior may depend on the JVM and underlying operating system.<\/span><\/p>\n<p><b>Common Constructors in the Thread Class<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">Thread<\/span><span style=\"font-weight: 400;\"> class provides several constructors to create and initialize thread instances. These constructors allow developers to specify thread names, associate <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> objects, or use default values.<\/span><\/p>\n<p><b>Thread()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Creates a new thread instance with default values and no specific task to execute until the <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method is defined.<\/span><\/p>\n<p><b>Thread(String name)<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Creates a thread and assigns it the specified name.<\/span><\/p>\n<p><b>Thread(Runnable target)<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Creates a thread with a <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> target, allowing the thread to execute the <\/span><span style=\"font-weight: 400;\">run()<\/span><span style=\"font-weight: 400;\"> method of the provided target object.<\/span><\/p>\n<p><b>Thread(Runnable target, String name)<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Creates a thread with a <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\"> target and assigns it the specified name, offering both task delegation and identification.<\/span><\/p>\n<p><b>Advanced Thread Lifecycle Concepts<\/b><\/p>\n<p><b>Transition Between States<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A Java thread transitions between states based on method calls and scheduling. For example, when <\/span><span style=\"font-weight: 400;\">sleep()<\/span><span style=\"font-weight: 400;\"> is called, the thread moves from Running to Blocked (Timed Waiting). When a resource becomes available or a condition is met, the thread transitions back to Runnable. Understanding these transitions is critical for effective thread management, especially when optimizing for performance or preventing concurrency issues.<\/span><\/p>\n<p><b>Timed Waiting State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Timed Waiting is a subtype of the Blocked state where a thread is waiting for a specified period. This state occurs when methods like <\/span><span style=\"font-weight: 400;\">sleep(milliseconds)<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">join(milliseconds)<\/span><span style=\"font-weight: 400;\">, or <\/span><span style=\"font-weight: 400;\">wait(milliseconds)<\/span><span style=\"font-weight: 400;\"> are used. After the defined time has elapsed, the thread returns to the Runnable state unless interrupted or explicitly resumed.<\/span><\/p>\n<p><b>Waiting State<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Unlike Timed Waiting, the Waiting state does not have a time limit. A thread remains in this state until another thread sends a signal to wake it. This is common with methods like <\/span><span style=\"font-weight: 400;\">wait()<\/span><span style=\"font-weight: 400;\"> without a timeout, <\/span><span style=\"font-weight: 400;\">join()<\/span><span style=\"font-weight: 400;\">, or waiting on an object\u2019s monitor without a specified delay.<\/span><\/p>\n<p><b>Termination and Cleanup<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Once a thread enters the Dead state, it cannot be restarted. Proper cleanup, such as closing I\/O streams or releasing locks, is essential before a thread terminates. Finalizers and shutdown hooks can be used to ensure that resources are properly handled, though they should be used with caution due to their potential impact on performance and maintainability.<\/span><\/p>\n<p><b>Thread States Illustrated with Code<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ThreadStateExample extends Thread {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void run() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System. out.println(&#171;Thread running&#8230;&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ThreadStateExample t1 = new ThreadStateExample();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;State after creation: &#187; + t1.getState());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;State after start(): &#187; + t1.getState());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(100);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;State after execution: &#187; + t1.getState());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This example prints the state of the thread at different stages: after creation, after starting, and after completion. It illustrates how threads transition across their lifecycle.<\/span><\/p>\n<p><b>Thread Methods Overview<\/b><\/p>\n<p><b>start()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Initiates a new thread of execution. Once called, the thread moves from the New state to Runnable and is eligible for CPU allocation.<\/span><\/p>\n<p><b>run()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Defines the code to execute in the thread. It should never be called directly for concurrent execution\u2014instead, use <\/span><span style=\"font-weight: 400;\">start()<\/span><span style=\"font-weight: 400;\"> to ensure the thread runs on a new call stack.<\/span><\/p>\n<p><b>sleep(milliseconds)<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Puts the current thread into a blocked state for a specific time, after which it moves to the Runnable state.<\/span><\/p>\n<p><b>join()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Waits for a thread to die. If <\/span><span style=\"font-weight: 400;\">join()<\/span><span style=\"font-weight: 400;\"> is called on a thread, the calling thread waits until the specified thread completes execution.<\/span><\/p>\n<p><b>yield()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Causes the currently executing thread to pause and allow other threads of equal priority to execute. It doesn\u2019t guarantee any thread will get CPU time, but suggests the scheduler.<\/span><\/p>\n<p><b>isAlive()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Checks whether a thread is still running or has completed execution. Returns true if the thread has been started and hasn\u2019t yet died.<\/span><\/p>\n<p><b>Thread Naming and Identification<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Each thread has a name, which can help with debugging or logging. By default, threads are named <\/span><span style=\"font-weight: 400;\">Thread-0<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">Thread-1<\/span><span style=\"font-weight: 400;\">, etc., but custom names can be assigned using constructors or the <\/span><span style=\"font-weight: 400;\">setName()<\/span><span style=\"font-weight: 400;\"> method.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Thread t1 = new Thread(&#171;MyCustomThread&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">System.out.println(&#171;Thread Name: &#187; + t1.getName());<\/span><\/p>\n<p><b>Java Thread Scheduler<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The thread scheduler is part of the JVM, responsible for deciding which thread to run next. It follows a preemptive or time-sliced round-robin algorithm, depending on the underlying operating system. The scheduler considers thread priorities but does not strictly follow them, especially on systems that do not support priority-based scheduling.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Understanding the non-deterministic nature of the scheduler is important. Developers should avoid relying on specific thread execution orders and instead use synchronization or coordination mechanisms for predictable results.<\/span><\/p>\n<p><b>Thread Synchronization in Java<\/b><\/p>\n<p><span style=\"font-weight: 400;\">When multiple threads access shared resources, synchronization is necessary to prevent data inconsistency and race conditions.<\/span><\/p>\n<p><b>The Synchronized Keyword<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Used to lock methods or code blocks so only one thread can execute them at a time. This helps prevent race conditions when multiple threads try to modify shared variables.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class Counter {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private int count = 0;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public synchronized void increment() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0count++;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public int getCount() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return count;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Static Synchronization<\/b><\/p>\n<p><span style=\"font-weight: 400;\">When a static method is synchronized, the lock is associated with the class, not an object instance. This is useful when multiple threads access static variables.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public static synchronized void staticMethod() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\/\/ synchronized on the class<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Synchronization Block<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Rather than synchronizing an entire method, a block within a method can be synchronized on a specific object.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public void update() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0synchronized(this) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ synchronized block<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This allows more control over what part of the code is locked, improving performance by reducing contention.<\/span><\/p>\n<p><b>Intrinsic Locks and Monitors<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Each object in Java has an intrinsic lock or monitor. When a thread enters a synchronized method or block, it acquires the lock associated with the object. Other threads attempting to enter synchronized code on the same object are blocked until the lock is released.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Improper use of synchronization can lead to deadlocks, performance bottlenecks, or thread starvation. It\u2019s essential to design thread-safe components carefully and avoid holding locks longer than necessary.<\/span><\/p>\n<p><b>Thread Communication: wait(), notify(), notifyAll()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Java provides inter-thread communication methods through the Object class, allowing threads to cooperate by sharing locks and coordinating their activities.<\/span><\/p>\n<p><b>wait()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Causes the current thread to release the lock and wait until another thread invokes <\/span><span style=\"font-weight: 400;\">notify()<\/span><span style=\"font-weight: 400;\"> or <\/span><span style=\"font-weight: 400;\">notifyAll()<\/span><span style=\"font-weight: 400;\"> on the same object.<\/span><\/p>\n<p><b>notify()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Wakes up a single waiting thread that is waiting on the object&#8217;s monitor.<\/span><\/p>\n<p><b>notifyAll()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Wakes up all waiting threads on the object. The awakened threads compete for the monitor, and only one can proceed.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">synchronized(obj) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0while (conditionNotMet) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0obj.wait();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\/\/ proceed when the condition is met<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This approach is common in producer-consumer problems, where one thread waits for data while another produces it.<\/span><\/p>\n<p><b>The Volatile Keyword<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">volatile<\/span><span style=\"font-weight: 400;\"> keyword ensures visibility of changes to variables across threads. When a variable is declared volatile, it prevents threads from caching the value and forces them to read it from main memory.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">private volatile boolean running = true;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is useful for simple flags or status indicators that are updated by one thread and read by others.<\/span><\/p>\n<p><b>Atomic Variables<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Java provides atomic classes such as <\/span><span style=\"font-weight: 400;\">AtomicInteger<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">AtomicBoolean<\/span><span style=\"font-weight: 400;\">, and <\/span><span style=\"font-weight: 400;\">AtomicReference<\/span><span style=\"font-weight: 400;\"> in the <\/span><span style=\"font-weight: 400;\">java.util.concurrent.atomic<\/span><span style=\"font-weight: 400;\"> package. These allow lock-free, thread-safe operations on single variables.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">AtomicInteger count = new AtomicInteger(0);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">count.incrementAndGet();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Atomic classes use low-level concurrency primitives to offer better performance than synchronization in some cases.<\/span><\/p>\n<p><b>Deadlocks in Java<\/b><\/p>\n<p><b>What is a Deadlock?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A <\/span><b>deadlock<\/b><span style=\"font-weight: 400;\"> occurs when two or more threads are blocked forever, waiting for each other to release locks. This happens when each thread holds a lock that another thread needs, creating a circular dependency. Deadlocks can cause applications to freeze or become unresponsive.<\/span><\/p>\n<p><b>Conditions for Deadlock<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Deadlock requires four conditions to hold simultaneously:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Mutual Exclusion<\/b><span style=\"font-weight: 400;\">: At least one resource is held in a non-shareable mode.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Hold and Wait<\/b><span style=\"font-weight: 400;\">: Threads holding resources can request additional resources.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>No Preemption<\/b><span style=\"font-weight: 400;\">: Resources cannot be forcibly taken from a thread.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Circular Wait<\/b><span style=\"font-weight: 400;\">: A cycle of threads exists where each thread waits for a resource held by the next thread.<\/span>&nbsp;<\/li>\n<\/ol>\n<p><b>Example of Deadlock<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class DeadlockDemo {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final Object resource1 = new Object();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final Object resource2 = new Object();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void method1() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0synchronized (resource1) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread 1: Locked resource 1&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try { Thread.sleep(50); } catch (InterruptedException e) {}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0synchronized (resource2) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread 1: Locked resource 2&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void method2() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0synchronized (resource2) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread 2: Locked resource 2&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try { Thread.sleep(50); } catch (InterruptedException e) {}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0synchronized (resource1) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Thread 2: Locked resource 1&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0DeadlockDemo demo = new DeadlockDemo();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t1 = new Thread(demo::method1);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t2 = new Thread(demo::method2);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t2.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Here, <\/span><span style=\"font-weight: 400;\">Thread 1<\/span><span style=\"font-weight: 400;\"> locks <\/span><span style=\"font-weight: 400;\">resource1<\/span><span style=\"font-weight: 400;\"> and waits for <\/span><span style=\"font-weight: 400;\">resource2<\/span><span style=\"font-weight: 400;\">, while <\/span><span style=\"font-weight: 400;\">Thread 2<\/span><span style=\"font-weight: 400;\"> locks <\/span><span style=\"font-weight: 400;\">resource2<\/span><span style=\"font-weight: 400;\"> and waits for <\/span><span style=\"font-weight: 400;\">resource1<\/span><span style=\"font-weight: 400;\">. This causes both threads to wait indefinitely.<\/span><\/p>\n<p><b>Detecting Deadlocks<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Thread Dumps:<\/b><span style=\"font-weight: 400;\"> Use <\/span><span style=\"font-weight: 400;\">jstack<\/span><span style=\"font-weight: 400;\"> or IDE thread dumps to identify deadlock cycles.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>JVM Tools:<\/b><span style=\"font-weight: 400;\"> Java Mission Control and VisualVM provide deadlock detection.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Logging:<\/b><span style=\"font-weight: 400;\"> Adding log statements before acquiring locks helps trace deadlocks.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Preventing Deadlocks<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Lock Ordering:<\/b><span style=\"font-weight: 400;\"> Acquire locks in a consistent global order across all threads.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Timeouts:<\/b><span style=\"font-weight: 400;\"> Use <\/span><span style=\"font-weight: 400;\">tryLock()<\/span><span style=\"font-weight: 400;\"> with timeouts (from <\/span><span style=\"font-weight: 400;\">java.util.concurrent.locks.Lock<\/span><span style=\"font-weight: 400;\">).<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Avoid Nested Locks:<\/b><span style=\"font-weight: 400;\"> Minimize synchronized blocks or avoid acquiring multiple locks.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Use Concurrency Utilities:<\/b><span style=\"font-weight: 400;\"> Replace manual locks with high-level abstractions.<\/span><\/li>\n<\/ul>\n<p><b>Thread Pools and Executors<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Managing threads efficiently is critical. Creating and destroying threads frequently is expensive, so Java provides thread pools to reuse threads.<\/span><\/p>\n<p><b>What is a Thread Pool?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A <\/span><b>thread pool<\/b><span style=\"font-weight: 400;\"> maintains a pool of worker threads ready to execute tasks. Tasks are submitted to the pool, and available threads pick them up. This avoids the overhead of creating new threads repeatedly.<\/span><\/p>\n<p><b>The Executor Framework<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Java&#8217;s <\/span><span style=\"font-weight: 400;\">java. Util. The concurrent<\/span><span style=\"font-weight: 400;\"> package includes the Executor framework, which simplifies thread pool usage.<\/span><\/p>\n<p><b>Creating Thread Pools with Executors<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.ExecutorService;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.Executors;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ThreadPoolExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ExecutorService executor = Executors.newFixedThreadPool(3);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable task = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; is executing task&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for (int i = 0; i &lt; 10; i++) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0executor.submit(task);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0executor.shutdown();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Types of Thread Pools<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>FixedThreadPool:<\/b><span style=\"font-weight: 400;\"> Creates a fixed number of threads.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CachedThreadPool:<\/b><span style=\"font-weight: 400;\"> Creates new threads as needed and reuses idle ones.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>SingleThreadExecutor:<\/b><span style=\"font-weight: 400;\"> Uses a single worker thread to execute tasks sequentially.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>ScheduledThreadPool:<\/b><span style=\"font-weight: 400;\"> Executes tasks after a delay or periodically.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Advantages of Using Thread Pools<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reuses existing threads, reducing overhead.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Controls the number of concurrent threads.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Offers built-in queue management.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Supports task scheduling.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Concurrency Utilities in <\/b><b>Java. Util.concurrent<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Beyond basic threading, Java provides powerful utilities to handle common concurrency problems.<\/span><\/p>\n<p><b>CountDownLatch<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A synchronization aid that allows one or more threads to wait until a set of operations completes.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.CountDownLatch;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class LatchExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) throws InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CountDownLatch latch = new CountDownLatch(3);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable task = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; finished work&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0latch.countDown();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0latch.await(); \/\/ main thread waits<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;All tasks completed&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>CyclicBarrier<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Allows a group of threads to wait for each other at a barrier point.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.CyclicBarrier;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class BarrierExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CyclicBarrier barrier = new CyclicBarrier(3, () -&gt; System.out.println(&#171;All threads reached barrier&#187;));<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable task = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; working&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(1000);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0barrier.await();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (Exception e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Semaphore<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Controls access to a resource by multiple threads by maintaining a set number of permits.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.Semaphore;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class SemaphoreExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private static final Semaphore semaphore = new Semaphore(2);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable task = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0semaphore.acquire();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; acquired permit&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(2000);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; released permit&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0semaphore.release();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for (int i = 0; i &lt; 5; i++) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Thread(task).start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Futures and Callables<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Java\u2019s <\/span><span style=\"font-weight: 400;\">Callable<\/span><span style=\"font-weight: 400;\"> interface allows tasks to return results and throw exceptions, unlike <\/span><span style=\"font-weight: 400;\">Runnable<\/span><span style=\"font-weight: 400;\">. Coupled with <\/span><span style=\"font-weight: 400;\">Future<\/span><span style=\"font-weight: 400;\">, it provides a way to retrieve task results asynchronously.<\/span><\/p>\n<p><b>Using Callable and Future<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.Callable;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.ExecutionException;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.ExecutorService;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.Executors;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.Future;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class CallableExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) throws ExecutionException, InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ExecutorService executor = Executors.newSingleThreadExecutor();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Callable&lt;String&gt; callableTask = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(1000);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return &#171;Task completed&#187;;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Future&lt;String&gt; future = executor.submit(callableTask);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Waiting for result&#8230;&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0String result = future.get(); \/\/ blocks until result available<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Result: &#187; + result);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0executor.shutdown();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Best Practices for Java Multithreading<\/b><\/p>\n<p><b>1. Minimize Synchronization Scope<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Only synchronize critical sections that access shared mutable data to reduce contention and improve performance.<\/span><\/p>\n<p><b>2. Prefer High-Level Concurrency Utilities<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Use <\/span><span style=\"font-weight: 400;\">Java. Util. Concurrent<\/span><span style=\"font-weight: 400;\"> package\u2019s utilities, such as thread pools, locks, and synchronization aids, instead of low-level <\/span><span style=\"font-weight: 400;\">synchronized<\/span><span style=\"font-weight: 400;\"> blocks or manual thread management.<\/span><\/p>\n<p><b>3. Avoid Deadlocks<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Use consistent lock ordering and minimize nested locks. Prefer lock timeouts and deadlock detection tools.<\/span><\/p>\n<p><b>4. Use Immutable Objects<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Immutable objects are naturally thread-safe because their state cannot change after creation, eliminating synchronization needs.<\/span><\/p>\n<p><b>5. Avoid Thread Interruption Ignorance<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Always handle <\/span><span style=\"font-weight: 400;\">InterruptedException<\/span><span style=\"font-weight: 400;\"> properly by either restoring the interrupt status or exiting promptly.<\/span><\/p>\n<p><b>6. Use Volatile for Flags<\/b><\/p>\n<p><span style=\"font-weight: 400;\">For simple flags or variables updated by one thread and read by others, use <\/span><span style=\"font-weight: 400;\">volatile<\/span><span style=\"font-weight: 400;\"> to ensure visibility.<\/span><\/p>\n<p><b>7. Prefer Executors over Manual Threads<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Executors provide better thread lifecycle management and resource optimization compared to manually managing threads.<\/span><\/p>\n<p><b>8. Document Threading Assumptions<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Document any assumptions about thread safety, synchronization, and expected concurrency behaviors to ease maintenance and reduce bugs.<\/span><\/p>\n<p><b>Thread Safety Concepts<\/b><\/p>\n<p><b>Immutable Objects<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Immutable classes cannot be modified after construction, making them inherently thread-safe.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public final class ImmutablePerson {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final String name;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public ImmutablePerson(String name) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.name = name;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public String getName() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return name;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Thread-Safe Collections<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Use classes from <\/span><span style=\"font-weight: 400;\">Java. Util. Concurrent<\/span><span style=\"font-weight: 400;\"> such as <\/span><span style=\"font-weight: 400;\">ConcurrentHashMap<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">CopyOnWriteArrayList<\/span><span style=\"font-weight: 400;\">, or synchronized wrappers from <\/span><span style=\"font-weight: 400;\">Collections.synchronizedXXX()<\/span><span style=\"font-weight: 400;\"> to safely use collections across threads.<\/span><\/p>\n<p><b>Handling Exceptions in Threads<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Exceptions thrown from threads are often ignored if not properly handled. Use these strategies:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Catch Exceptions Inside <\/b><b>run()<\/b><b> or <\/b><b>call()<\/b><b> Methods:<\/b><span style=\"font-weight: 400;\"> Prevent thread termination.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Set UncaughtExceptionHandler:<\/b><span style=\"font-weight: 400;\"> Catch unhandled exceptions.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Thread t = new Thread(() -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0throw new RuntimeException(&#171;Exception in thread&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">t.setUncaughtExceptionHandler((thread, throwable) -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Caught exception from &#187; + thread.getName() + &#171;: &#187; + throwable.getMessage());<\/span><\/p>\n<p><span style=\"font-weight: 400;\">});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">t.start();<\/span><\/p>\n<p><b>Thread Local Variables<\/b><\/p>\n<p><span style=\"font-weight: 400;\">ThreadLocal<\/span><span style=\"font-weight: 400;\"> provides thread-local variables, where each thread has its isolated copy. This helps avoid shared state issues without synchronization.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">ThreadLocal&lt;Integer&gt; threadLocal = ThreadLocal.withInitial(() -&gt; 1);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">System.out.println(threadLocal.get()); \/\/ prints 1<\/span><\/p>\n<p><span style=\"font-weight: 400;\">threadLocal.set(5);<\/span><\/p>\n<p><b>Java Memory Model (JMM) Basics<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Understanding the JMM is key to writing correct multithreaded programs. It defines how threads interact through memory and how changes to variables become visible across threads.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Happens-Before Relationship:<\/b><span style=\"font-weight: 400;\"> Guarantees visibility and ordering of operations.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Synchronization:<\/b><span style=\"font-weight: 400;\"> Provides happens-before guarantees.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Volatile Variables:<\/b><span style=\"font-weight: 400;\"> Ensure visibility of changes.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Final Fields:<\/b><span style=\"font-weight: 400;\"> Properly published immutable fields ensure safe access.<\/span><\/li>\n<\/ul>\n<p><b>Advanced Synchronization Techniques<\/b><\/p>\n<p><b>Reentrant Locks (<\/b><b>java.util.concurrent.locks.ReentrantLock<\/b><b>)<\/b><\/p>\n<p><span style=\"font-weight: 400;\">While <\/span><span style=\"font-weight: 400;\">synchronized<\/span><span style=\"font-weight: 400;\"> blocks are simple and effective, <\/span><span style=\"font-weight: 400;\">ReentrantLock<\/span><span style=\"font-weight: 400;\"> from the <\/span><span style=\"font-weight: 400;\">java.util.concurrent.The locks<\/span><span style=\"font-weight: 400;\"> package offers more advanced locking capabilities.<\/span><\/p>\n<p><b>Features of ReentrantLock<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Explicit lock and unlock control.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Ability to attempt lock acquisition with timeout (<\/span><span style=\"font-weight: 400;\">tryLock<\/span><span style=\"font-weight: 400;\">).<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Supports fairness policies to avoid thread starvation.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Provides condition variables for complex wait\/notify scenarios.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Example Usage<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.ReentrantLock;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ReentrantLockExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final ReentrantLock lock = new ReentrantLock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void performTask() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.lock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; acquired lock&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Critical section code<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.unlock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; released lock&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ReentrantLockExample example = new ReentrantLockExample();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable task = example::performTask;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t1 = new Thread(task, &#171;Thread-1&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t2 = new Thread(task, &#171;Thread-2&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t2.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Condition Variables<\/b><\/p>\n<p><span style=\"font-weight: 400;\">ReentrantLock<\/span><span style=\"font-weight: 400;\"> supports <\/span><span style=\"font-weight: 400;\">Condition<\/span><span style=\"font-weight: 400;\"> objects, which are more flexible than <\/span><span style=\"font-weight: 400;\">Object.wait()<\/span><span style=\"font-weight: 400;\"> and <\/span><span style=\"font-weight: 400;\">Object.notify()<\/span><span style=\"font-weight: 400;\">. Conditions allow multiple wait-sets per lock.<\/span><\/p>\n<p><b>Example of Condition Usage<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.Condition;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.Lock;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.ReentrantLock;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ConditionExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final Lock lock = new ReentrantLock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final Condition condition = lock.newCondition();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private boolean ready = false;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void awaitReady() throws InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.lock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (!ready) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0condition.await();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; is proceeding&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.unlock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void signalReady() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.lock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ready = true;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0condition.signalAll();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lock.unlock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) throws InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ConditionExample example = new ConditionExample();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread waitingThread = new Thread(() -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0example.awaitReady();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.currentThread().interrupt();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}, &#171;WaitingThread&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0waitingThread.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(2000);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread signalingThread = new Thread(example::signalReady, &#171;SignalingThread&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0signalingThread.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>ReadWriteLock<\/b><\/p>\n<p><span style=\"font-weight: 400;\">For scenarios with many readers but few writers, <\/span><span style=\"font-weight: 400;\">ReadWriteLock<\/span><span style=\"font-weight: 400;\"> allows multiple threads to read simultaneously while restricting write access.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.ReadWriteLock;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.locks.ReentrantReadWriteLock;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ReadWriteLockExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final ReadWriteLock rwLock = new ReentrantReadWriteLock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private int value = 0;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public void write(int newValue) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rwLock.writeLock().lock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0value = newValue;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; wrote value: &#187; + newValue);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rwLock.writeLock().unlock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public int read() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rwLock.readLock().lock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; read value: &#187; + value);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return value;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rwLock.readLock().unlock();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ReadWriteLockExample example = new ReadWriteLockExample();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable readTask = example::read;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable writeTask = () -&gt; example.write((int) (Math.random() * 100));<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread writer = new Thread(writeTask, &#171;WriterThread&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread reader1 = new Thread(readTask, &#171;ReaderThread-1&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread reader2 = new Thread(readTask, &#171;ReaderThread-2&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reader1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reader2.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0writer.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Thread Communication: Wait, Notify, and NotifyAll<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Threads often need to communicate, especially when coordinating access to shared resources.<\/span><\/p>\n<p><b>Using <\/b><b>wait()<\/b><b> and <\/b><b>notify()<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">wait()<\/span><span style=\"font-weight: 400;\"> causes the current thread to release the lock and enter the waiting state.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Notify ()<\/span><span style=\"font-weight: 400;\"> wakes up one waiting thread.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">notifyAll()<\/span><span style=\"font-weight: 400;\"> wakes up all waiting threads.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Example: Producer-Consumer Using <\/b><b>wait()<\/b><b> and <\/b><b>notify()<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.LinkedList;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.Queue;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ProducerConsumer {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final Queue&lt;Integer&gt; queue = new LinkedList&lt;&gt;();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final int LIMIT = 5;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public synchronized void produce() throws InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int value = 0;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (true) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (queue.size() == LIMIT) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wait();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0queue.offer(value);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Produced: &#187; + value);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0value++;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0notify();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(500);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public synchronized void consume() throws InterruptedException {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (true) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (queue.isEmpty()) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wait();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int value = queue.poll();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Consumed: &#187; + value);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0notify();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(500);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ProducerConsumer pc = new ProducerConsumer();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread producer = new Thread(() -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pc.produce();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.currentThread().interrupt();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread consumer = new Thread(() -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pc.consume();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.currentThread().interrupt();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0producer.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0consumer.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Concurrent Collections<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Java provides thread-safe collections optimized for concurrent access.<\/span><\/p>\n<p><b>ConcurrentHashMap<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A hash table supporting full concurrency of retrievals and adjustable concurrency for updates.<\/span><\/p>\n<p><b>Example<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.ConcurrentHashMap;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class ConcurrentHashMapExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ConcurrentHashMap&lt;String, Integer&gt; map = new ConcurrentHashMap&lt;&gt;();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Runnable writer = () -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for (int i = 0; i &lt; 5; i++) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0map.put(Thread.currentThread().getName() + &#171;-&#187; + i, i);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(Thread.currentThread().getName() + &#187; put: &#187; + i);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.sleep(50);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (InterruptedException e) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread.currentThread().interrupt();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t1 = new Thread(writer, &#171;Writer1&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Thread t2 = new Thread(writer, &#171;Writer2&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t1.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0t2.start();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Other Collections<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">CopyOnWriteArrayList<\/span><span style=\"font-weight: 400;\"> for mostly-read lists.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">BlockingQueue<\/span><span style=\"font-weight: 400;\"> implementations (<\/span><span style=\"font-weight: 400;\">ArrayBlockingQueue<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">LinkedBlockingQueue<\/span><span style=\"font-weight: 400;\">) for producer-consumer.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">ConcurrentSkipListMap<\/span><span style=\"font-weight: 400;\"> for sorted maps.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Fork\/Join Framework<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Introduced in Java 7, the Fork\/Join framework supports parallelism by recursively splitting tasks.<\/span><\/p>\n<p><b>ForkJoinTask, RecursiveTask, and RecursiveAction<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>RecursiveTask:<\/b><span style=\"font-weight: 400;\"> Returns a result.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>RecursiveAction:<\/b><span style=\"font-weight: 400;\"> No result (void).<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Example: Computing Fibonacci Numbers<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.ForkJoinPool;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.RecursiveTask;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class FibonacciTask extends RecursiveTask&lt;Integer&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0private final int n;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public FibonacciTask(int n) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.n = n;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0@Override<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0protected Integer compute() {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (n &lt;= 1) return n;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FibonacciTask f1 = new FibonacciTask(n &#8212; 1);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0f1.fork(); \/\/ fork a new subtask<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FibonacciTask f2 = new FibonacciTask(n &#8212; 2);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int result2 = f2.compute(); \/\/ compute directly<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int result1 = f1.join(); \/\/ wait for result<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return result1 + result2;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ForkJoinPool pool = new ForkJoinPool();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int n = 10;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int result = pool.invoke(new FibonacciTask(n));<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System.out.println(&#171;Fibonacci number &#187; + n + &#187; is &#187; + result);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Reactive and Asynchronous Programming Basics<\/b><\/p>\n<p><b>CompletableFuture<\/b><\/p>\n<p><span style=\"font-weight: 400;\">CompletableFuture<\/span><span style=\"font-weight: 400;\"> supports async programming and chaining.<\/span><\/p>\n<p><b>Example<\/b><\/p>\n<p><span style=\"font-weight: 400;\">java<\/span><\/p>\n<p><span style=\"font-weight: 400;\">CopyEdit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import java.util.concurrent.CompletableFuture;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">public class CompletableFutureExample {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0public static void main(String[] args) {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CompletableFuture.supplyAsync(() -&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0System. out.println(&#171;Running task&#8230;&#187;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return &#171;Hello&#187;;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}).thenApply(s -&gt; s + &#187; World&#187;)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.thenAccept(System.out::println)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.join();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><b>Performance Tuning and Monitoring<\/b><\/p>\n<p><b>Tips for Optimizing Multithreaded Java Programs<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Minimize locking and contention.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use efficient concurrent collections.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Prefer thread pools to avoid thread creation overhead.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Avoid blocking operations where possible.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Profile thread usage and CPU time.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use tools like VisualVM, Java Mission Control for monitoring.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><b>Debugging and Testing Multithreaded Code<\/b><\/p>\n<p><b>Techniques<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use thread dumps (<\/span><span style=\"font-weight: 400;\">jstack<\/span><span style=\"font-weight: 400;\">) to analyze stuck or deadlocked threads.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Log thread activity and synchronization points.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use thread sanitizer tools or concurrency testing frameworks (e.g., IBM ConTest, JCStress).<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write unit tests using tools like JUnit with concurrency utilities.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use deterministic scheduling tools to reproduce concurrency bugs.<\/span><\/li>\n<\/ul>\n<p><b>Final Thoughts on Java Threading and Concurrency<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Mastering threading and concurrency in Java is essential for developing high-performance, scalable, and responsive applications. The ability to run multiple tasks simultaneously can significantly improve application efficiency, especially in today\u2019s multi-core and distributed computing environments.<\/span><\/p>\n<p><b>Key Takeaways<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Threads are powerful but complex:<\/b><span style=\"font-weight: 400;\"> While threads can boost performance, improper use leads to subtle bugs like race conditions, deadlocks, and resource starvation. Understanding thread lifecycle, synchronization, and communication mechanisms is critical.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Use the right tools for the job:<\/b><span style=\"font-weight: 400;\"> Java provides a rich set of concurrency utilities\u2014from basic <\/span><span style=\"font-weight: 400;\">synchronized<\/span><span style=\"font-weight: 400;\"> blocks to advanced constructs like <\/span><span style=\"font-weight: 400;\">ReentrantLock<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">ConcurrentHashMap<\/span><span style=\"font-weight: 400;\">, and the Fork\/Join framework. Leveraging these tools correctly reduces boilerplate code and avoids common pitfalls.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Thread safety is paramount:<\/b><span style=\"font-weight: 400;\"> Always ensure that shared data is accessed safely using synchronization or concurrent data structures. Immutable objects, thread confinement, and atomic variables are effective strategies to simplify thread safety.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Design with concurrency in mind:<\/b><span style=\"font-weight: 400;\"> Multithreading should be considered early in design, especially for applications involving I\/O, UI responsiveness, or complex task parallelism. Proper architectural decisions reduce the complexity of concurrent code later.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Testing and debugging are challenging but doable:<\/b><span style=\"font-weight: 400;\"> Use dedicated testing frameworks and profiling tools to uncover concurrency issues. Log extensively and analyze thread dumps to diagnose problems like deadlocks or thread leaks.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Performance tuning requires profiling:<\/b><span style=\"font-weight: 400;\"> Blind optimization can be counterproductive. Profile your application to identify bottlenecks, and apply targeted improvements such as reducing contention, tuning thread pools, or optimizing task granularity.<\/span>&nbsp;<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Stay up-to-date:<\/b><span style=\"font-weight: 400;\"> Java\u2019s concurrency landscape evolves with new frameworks and best practices. Explore reactive programming (CompletableFuture, Project Reactor), parallel streams, and emerging APIs to write modern concurrent code.<\/span>&nbsp;<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Concurrency programming is a challenging but rewarding skill that opens the door to creating sophisticated software able to fully utilize modern hardware capabilities. With careful design, thoughtful synchronization, and ongoing learning, you can harness Java\u2019s threading features to build fast, efficient, and robust applications.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A thread in Java is the smallest unit of execution within a program. Every Java application starts with a single thread, known as the main thread, which is initiated by the Java Virtual Machine (JVM) at the start of program execution. The main thread begins by invoking the main() method, from which the program&#8217;s operations commence. In Java, a thread represents a separate path of execution. Java programs can utilize multiple threads to execute tasks concurrently, allowing for more efficient use of system [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1049,1053],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/posts\/983"}],"collection":[{"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/comments?post=983"}],"version-history":[{"count":2,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/posts\/983\/revisions"}],"predecessor-version":[{"id":9706,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/posts\/983\/revisions\/9706"}],"wp:attachment":[{"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/media?parent=983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/categories?post=983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.certbolt.com\/certification\/wp-json\/wp\/v2\/tags?post=983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}