Java Threads Series – Zero to Hero (Part 1)

posted 2 min read

In this series, we’ll learn the what’s and how’s of threads in Java — from the basics of concurrency to practical multithreading patterns used in real-world systems.

What are threads?

A thread is the smallest unit of execution in a process. A Java program (JVM process) can contain many threads that execute code concurrently while sharing the same process memory. Threads run inside a process and share its heap and static data.
Each thread:

  • Shares the process’s heap and static data.
  • Has its own call stack and CPU register context.

Imagine a kitchen (process). Each cook is a thread. They share the same pantry (memory), but each cook can work on different tasks (methods, code) at the same time — prepping, stirring, plating.

⚡Why do we need threads?

Threads are mainly used to achieve parallelism and concurrency. When hardware has multiple CPU cores, multiple threads can run in parallel to shorten latency for CPU-bound tasks.

Thread Lifecycle

NEW — thread object created but not started yet.

RUNNABLE — executing on CPU or ready to run (OS-dependent; JVM treats this as runnable).

BLOCKED — waiting for a monitor lock (entering synchronized block/method).

WAITING — waiting indefinitely for another thread to perform a particular action (e.g., Object.wait() without timeout, Thread.join() without timeout).

TIMED_WAITING — waiting with a timeout (e.g., Thread.sleep(ms), wait(ms), join(ms)).

TERMINATED — finished execution (exited run()).

public class ThreadLifecycleDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            System.out.println("Inside run(): " + Thread.currentThread().getState());
            try {
                Thread.sleep(200); // TIMED_WAITING
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        System.out.println("After creation: " + t.getState()); // NEW
        t.start();
        System.out.println("After start: " + t.getState());    // RUNNABLE
        t.join();
        System.out.println("After join: " + t.getState());     // TERMINATED
    }
}

Ways to create a thread

  1. Extending Thread :

You create a subclass of Thread and override run(). Starting the thread calls start() which eventually invokes your run() on a new OS-scheduled thread.

class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(getName() + " started");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println(getName() + " interrupted");
        }
        System.out.println(getName() + " finished");
    }
}

public class ExtendsThreadDemo {
    public static void main(String[] args) {
        Thread t = new MyThread("worker-1");
        t.start(); // spawns a new thread
    }
}
  1. Implementing Runnable :
    You implement Runnable to describe the task. Then pass it to a Thread or—preferably—to an ExecutorService.
class Worker implements Runnable {
    private final String name;
    Worker(String name) { this.name = name; }

    @Override
    public void run() {
        System.out.println(name + " started");
        try { Thread.sleep(300); } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println(name + " finished");
    }
}

public class RunnableDirectDemo {
    public static void main(String[] args) {
        Thread t = new Thread(new Worker("worker-2"));
        t.start();
    }
}

NOTE : Implementing Runnable is generally preferred over extending Thread to create a new thread because if a class extends thread, it can not extend any other class as java does not support multiple inheritance.

2 Comments

3 votes
2
2 votes
2

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

TypeScript Complexity Has Finally Reached the Point of Total Absurdity

Karol Modelskiverified - Apr 23

Your Tech Stack Isn’t Your Ceiling. Your Story Is

Karol Modelskiverified - Apr 9

Java Threads – Zero to Hero (Part 2)

Madhu - Dec 11, 2025

Tuesday Coding Tip 02 - Template with type-specific API

Jakub Neruda - Mar 10
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

8 comments
7 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!