Lesson Completion
Back to course

Creating Threads: Three Ways to Spawn Concurrent Tasks

Advanced
25 minutes4.7Java

1. The Hook (The "Byte-Sized" Intro)

In a Nutshell: Three ways to create threads: (1) Extend Thread class (simple but limits inheritance), (2) Implement Runnable interface (preferred—separates task from thread), (3) Use Callable<V> (returns value, throws exceptions). start() creates new thread and calls run(). Calling run() directly executes in current thread (no concurrency!)Java 8+ allows lambda expressions for Runnable/Callable.

Think of hiring employees. Thread class = hiring full-time employee (comes with overhead). Runnable = hiring contractor (flexible, reusable). Callable = contractor who delivers results!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Thread class: Buy a car (comes with engine built-in)
  • Runnable: Buy engine separately, install in any car (flexibility)
  • Callable: Engine with odometer (returns mileage data)

3. Technical Mastery

Method 1: Extending Thread Class

java
class MyThread extends Thread { @Override public void run() { System.out.println("Thread running: " + getName()); } } // Usage MyThread t = new MyThread(); t.start(); // ✅ Creates new thread // t.run(); // ❌ Runs in current thread!

Method 2: Implementing Runnable (Preferred)

java
class MyTask implements Runnable { @Override public void run() { System.out.println("Task running"); } } Thread t = new Thread(new MyTask()); t.start();

Method 3: Callable with Future

java
class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { return 42; // Can return value! } } ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> future = executor.submit(new MyCallable()); Integer result = future.get(); // Blocks until complete

4. Interactive & Applied Code

java
import java.util.concurrent.*; public class ThreadCreationDemo { public static void main(String[] args) throws Exception { // METHOD 1: Extend Thread Thread t1 = new MyThread("Thread-1"); t1.start(); // METHOD 2: Runnable (anonymous class) Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("Runnable via anonymous class"); } }); t2.start(); // METHOD 3: Runnable (lambda - Java 8+) Thread t3 = new Thread(() -> { System.out.println("Runnable via lambda"); }); t3.start(); // METHOD 4: Callable with ExecutorService ExecutorService executor = Executors.newSingleThreadExecutor(); Callable<String> task = () -> { Thread.sleep(1000); return "Result from Callable"; }; Future<String> future = executor.submit(task); System.out.println("Waiting for result..."); String result = future.get(); // Blocking call System.out.println("Got: " + result); executor.shutdown(); // Demonstrate start() vs run() demonstrateStartVsRun(); } static void demonstrateStartVsRun() { System.out.println("\n=== start() vs run() ==="); Thread t = new Thread(() -> { System.out.println("Inside run(): " + Thread.currentThread().getName()); }); System.out.println("Calling run() directly:"); t.run(); // Runs in main thread! System.out.println("Calling start():"); t.start(); // Creates new thread! } } class MyThread extends Thread { public MyThread(String name) { super(name); } @Override public void run() { System.out.println("MyThread running: " + getName()); } }

5. The Comparison & Decision Layer

MethodProsConsUse When
Extend ThreadSimpleNo multiple inheritanceQuick prototypes
Implement RunnableFlexible, reusableVerbose (pre-Java 8)Production code
CallableReturns value, throws exceptionsRequires ExecutorNeed results

6. The "Interview Corner"

The "Killer" Interview Question: "Why is implementing Runnable preferred over extending Thread?" Answer:

  1. Java single inheritance: Can't extend another class if extending Thread
  2. Separation of concerns: Task (Runnable) separate from execution mechanism (Thread)
  3. Reusability: Same Runnable can be submitted to thread pools
java
// ❌ BAD: Locked into Thread class MyTask extends Thread { // Cannot extend DatabaseConnection! } // ✅ GOOD: Can extend whatever you need class MyTask extends DatabaseConnection implements Runnable { // Flexible! }

Pro-Tip: Always call start(), never run():

java
Thread t = new Thread(() -> System.out.println(Thread.currentThread().getName())); t.run(); // ❌ Prints "main" (runs in current thread!) t.start(); // ✅ Prints "Thread-0" (new thread created)

Topics Covered

Java FundamentalsConcurrency

Tags

#java#multithreading#threads#concurrency#parallelism

Last Updated

2025-02-01