Understanding Multiple Threads in Java

Introduction
In Java programming, achieving parallel execution of tasks is made possible using multithreading. This blog explores how to create and run multiple threads concurrently, why using start() is critical, how scheduling works, and additional tips like using sleep() for clearer outputs.


Demonstrating Multiple Threads

Let's start with a simple example. We define two threads—one to say “Hi” and another to say “Hello”.

class HiThread extends Thread {
  public void run() {
    for(int i = 0; i < 5; i++) {
      System.out.println("Hi");
      try { Thread.sleep(500); } catch(Exception e) {}
    }
  }
}

class HelloThread extends Thread {
  public void run() {
    for(int i = 0; i < 5; i++) {
      System.out.println("Hello");
      try { Thread.sleep(500); } catch(Exception e) {}
    }
  }
}

public class MultiThreadApp {
  public static void main(String[] args) {
    new HiThread().start();
    new HelloThread().start();
  }
}

Notice the Thread.sleep(500) call inside each loop. It slows execution for half a second, making it easier to see interleaved outputs.


Understanding Interleaving of Output

When both threads run, you might see:

  • Hi Hello Hi Hello...
  • Hello Hi Hello Hi...
  • Or even a mixed sequence.

This happens because thread execution is controlled by the operating system's scheduler, not by your code directly.


How Java Thread Scheduling Works

After initiating threads using start(), the OS scheduler decides which thread gets CPU time and when. It uses techniques like time-slicing and priorities to manage execution. On multi-core processors, true parallel execution is also possible.


Creating Threads: Two Approaches

  • Extending Thread: Inherit from the Thread class and override its run() method.
  • Implementing Runnable: Implement the Runnable interface and pass its instance to a Thread constructor.

Thread Priorities

Each thread in Java has a priority, ranging from Thread.MIN_PRIORITY (1) to Thread.MAX_PRIORITY (10). The default is Thread.NORM_PRIORITY (5). While priorities suggest scheduling order to the JVM, the OS ultimately controls execution, so results may vary.


Managing Thread Safety

When multiple threads modify shared data, issues such as race conditions may arise. Even though this video doesn’t go deep into that, it's important to know that Java provides:

  • synchronized methods/blocks
  • Volatile variables
  • Thread-safe collections and atomic classes

Key Takeaways

  • You can run multiple Java threads concurrently using start().
  • Using sleep() helps demonstrate clearer interleaving of outputs.
  • The OS scheduler governs thread execution order and timing.
  • Java supports threading via either extending Thread or implementing Runnable.
  • Thread priorities exist, but exact scheduling is not guaranteed.
  • Concurrency introduces challenges like race conditions, requiring synchronization.

Conclusion

Mastering multiple threads in Java is a vital skill—essential for building responsive and efficient applications. While this guide offers a solid starting point, the real power lies in managing synchronization, priorities, and advanced concurrency tools.

Comments

Popular posts from this blog

Spring Boot on AWS EC2: Upload to S3 Securely Using IAM Role

Java Streams Intermediate Operations Explained with Examples

ConcurrentHashMap vs Synchronized HashMap in Java