πŸš€ Java Advanced
Estimated reading: 5 minutes 29 views

πŸ”„ Java Threads – The Complete Guide to Multithreading in Java


🧲 Introduction – Why Learn Java Threads?

Imagine you’re building a responsive app that plays music, downloads files, and allows real-time user interaction β€” all at the same time. Traditional code runs sequentially, which would make such an app sluggish or even unresponsive. That’s where Java Threads and multithreading come into play.

Java Threads enable concurrent execution of two or more parts of a program for maximum CPU utilization. They are fundamental in writing efficient, scalable, and high-performing Java applications β€” especially in games, web servers, and real-time systems.

βœ… By the end of this guide, you’ll understand:

  • What a thread is in Java
  • How to create and manage threads
  • Thread lifecycle and states
  • Thread synchronization & inter-thread communication
  • Real-world multithreading use cases

πŸ”‘ What Is a Java Thread?

A thread is a lightweight subprocess β€” the smallest unit of processing. Java supports multithreading via the java.lang.Thread class and the Runnable interface.

πŸ“˜ Multithreading means executing multiple threads simultaneously to perform multitasking.


🧡 Creating a Thread in Java

Java provides two ways to create threads:

1️⃣ Extending the Thread Class

class MyThread extends Thread {
    public void run() {
        System.out.println("Thread is running using Thread class.");
    }

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();  // Start the thread
    }
}

βœ… Explanation:

  • MyThread extends Thread, and we override the run() method with the code we want to execute.
  • start() triggers the run() method in a new thread of execution.

2️⃣ Implementing the Runnable Interface

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread is running using Runnable interface.");
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        t1.start();  // Start the thread
    }
}

βœ… Explanation:

  • MyRunnable implements Runnable, which requires a run() method.
  • The Runnable object is passed to a Thread instance, which is then started.

πŸ’‘ Best Practice: Use Runnable when you want to extend another class, as Java supports only single inheritance.


πŸ”„ Java Thread Lifecycle

A Java thread has five major states:

StateDescription
NewThread object is created but not started
RunnableThread is ready to run and waiting for CPU time
RunningThread is executing its run() method
Blocked/WaitingThread is paused and waiting for a resource or signal
TerminatedThread has finished executing or was forcefully stopped

πŸ“˜ Use getState() to check the current thread state.


🧠 Java Thread Methods (Essential)

MethodDescription
start()Starts thread and calls run() method
run()Entry point for thread execution
sleep(ms)Pauses thread for given milliseconds
join()Waits for a thread to die
isAlive()Checks if thread is alive
yield()Hints to scheduler to give other threads a chance
interrupt()Interrupts a thread

⚠️ Warning: Avoid using stop() as it’s deprecated due to safety concerns.


πŸ”’ Java Thread Synchronization

Multiple threads accessing the same resource can lead to race conditions. Java provides synchronization to handle this.

πŸ” Synchronized Block Example

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

βœ… Explanation:

  • The synchronized keyword ensures that only one thread can access increment() at a time.

πŸ’‘ Tip: Synchronize only the critical section of code for better performance.


πŸ”„ Inter-Thread Communication – wait(), notify(), notifyAll()

Java threads can communicate using these three methods (must be used in synchronized blocks):

class SharedResource {
    boolean flag = false;

    synchronized void waitForIt() throws InterruptedException {
        while (!flag) {
            wait();  // releases lock
        }
        System.out.println("Thread resumed after notification");
    }

    synchronized void notifyIt() {
        flag = true;
        notify();  // wakes up waiting thread
    }
}

βœ… Use Case: Producer-consumer problems where one thread waits for another to complete a task.


βš™οΈ Real-World Use Case: Parallel File Downloads

class FileDownloader extends Thread {
    private String file;

    FileDownloader(String file) {
        this.file = file;
    }

    public void run() {
        System.out.println("Downloading: " + file);
        // simulate download time
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        System.out.println("Completed: " + file);
    }

    public static void main(String[] args) {
        new FileDownloader("file1.txt").start();
        new FileDownloader("file2.txt").start();
        new FileDownloader("file3.txt").start();
    }
}

βœ… Explanation:

  • Each file is downloaded in parallel using a separate thread.
  • sleep() simulates time taken to download.

🧰 Thread Pools (Advanced Java)

Instead of creating new threads every time (which is costly), use ThreadPoolExecutor or Executors.newFixedThreadPool():

import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        for (int i = 1; i <= 5; i++) {
            int task = i;
            executor.execute(() -> {
                System.out.println("Executing task " + task);
            });
        }

        executor.shutdown();
    }
}

πŸ’‘ Benefit: Efficient thread management for large-scale concurrent apps.


🧼 Best Practices for Java Threads

  • βœ… Use Runnable or Callable with thread pools over raw Thread for production
  • βœ… Always shutdown() ExecutorService
  • πŸ”’ Synchronize access to shared resources
  • ❗ Avoid using deprecated methods like stop(), suspend(), or resume()
  • βœ… Use AtomicInteger, ConcurrentHashMap, etc., for thread-safe operations

πŸ“Œ Summary

Java Threads enable developers to write concurrent, high-performance applications by leveraging multicore processors. From simple parallel tasks to managing thread pools β€” understanding thread management is key to mastering Java.

πŸ“˜ Key Takeaways:

  • Learn both Thread and Runnable creation styles
  • Understand the lifecycle and core methods
  • Handle thread safety using synchronization
  • Optimize performance using thread pools

❓FAQs – Java Threads

❓ What is the difference between start() and run()?

start() creates a new thread and calls run(); calling run() directly does not start a new thread.

❓ Can we restart a thread in Java?

No, once a thread is terminated, it cannot be restarted. You need to create a new thread object.

❓ What is a daemon thread?

A daemon thread is a low-priority thread that runs in the background (like garbage collector). Use setDaemon(true).

❓ How to stop a thread safely?

Use a flag (e.g., volatile boolean running = false) and check it inside run() to stop execution.

❓ When should I use ThreadPool?

Use thread pools when you need to execute many short-lived tasks to avoid thread creation overhead.


Share Now :

Leave a Reply

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

Share

Java Threads

Or Copy Link

CONTENTS
Scroll to Top