CodeToConcept
About

java

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

Sample Question

Think it through, then check the tutorial.

CodeToConcept

Quickly learn through simple, structured, and practical coding tutorials. Build your confidence from step zero to real-world experience.

© 2026 CodeToConcept. All rights reserved.

Quick Links

AboutTutorials

Tutorials

JavaHTMLCSS

Support

Privacy PolicyTerms of ServiceContact
GitHubTwitterYouTube

Java Thread Class

Run each complete program separately. Its required helper classes and imports are included in the same code block. Short syntax fragments explain individual operations.

A thread lets a program make progress on a separate path of execution. For example, one task can prepare a result while another waits for input. Thread represents that running activity and provides operations for starting, observing, and coordinating it.

Instead of performing every task one after another, multiple threads can allow different tasks to make progress concurrently.

Java provides the Thread class to create and manage threads.

The Thread class belongs to the java.lang package.

Therefore, it does not need to be imported explicitly.

Thread

What is the Thread Class?

Thread is a class provided by Java that represents a thread of execution.

It provides methods for:

  • Creating threads
  • Starting threads
  • Controlling thread execution
  • Checking thread state
  • Waiting for another thread
  • Interrupting a thread
  • Getting thread information

A simple thread can be created by extending the Thread class.

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

Then:

MyThread thread = new MyThread();
 
thread.start();

Why Do We Need Threads?

Consider a program that performs two independent tasks:

Task 1 → Download a file
Task 2 → Process data

Without multiple threads, the program may execute them sequentially:

Task 1
  ↓
Task 2

With multiple threads, both tasks can make progress concurrently:

Thread 1 → Download file
Thread 2 → Process data

This can make applications more responsive and can improve throughput when tasks can execute concurrently.

However, using multiple threads also introduces challenges such as synchronization, shared data, and thread coordination.

Creating a Thread by Extending Thread

One way to create a thread is to extend the Thread class.

Example

class MyThread extends Thread {
 
    @Override
    public void run() {
        System.out.println("My thread is running");
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        MyThread thread = new MyThread();
 
        thread.start();
    }
}

Possible output:

My thread is running

The important method here is run().

But we should not normally call run() directly to start a new thread.

Instead, we call start().

start() vs run()

This is one of the most important concepts when learning Java threads.

Using start()

thread.start();

start() asks the JVM to start a new thread of execution, which will then invoke the thread's run() method.

Using run()

thread.run();

Calling run() directly is just a normal method call. It does not start a new thread.

For example:

class MyThread extends Thread {
 
    @Override
    public void run() {
        System.out.println(
            "Running: " +
            Thread.currentThread().getName()
        );
    }
}

Then:

MyThread thread = new MyThread();
 
thread.run();

The run() method executes on the current thread rather than starting a new thread.

But:

thread.start();

starts a separate thread of execution.

Remember:

start()
   ↓
Starts a new thread
   ↓
run()

Whereas:

run()
   ↓
Normal method call
   ↓
No new thread

The run() Method

The run() method contains the work that the thread should perform.

Example

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 5; i++) {
            System.out.println(i);
        }
    }
}

Then:

MyThread thread = new MyThread();
 
thread.start();

The JVM executes the run() method on the newly started thread.

Naming a Thread

A thread can have a name.

Thread thread = new Thread();
 
thread.setName("Worker-Thread");
 
thread.start();

Or a name can be supplied when creating the thread:

Thread thread =
    new Thread("Worker-Thread");

The thread name can be retrieved using:

thread.getName();

Example

System.out.println(thread.getName());

Thread.currentThread()

The currentThread() method returns the thread that is currently executing the code.

Example

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        Thread current =
            Thread.currentThread();
 
        System.out.println(
            current.getName()
        );
    }
}

If the thread is named Worker, the output may be:

Worker

A shorter version is:

System.out.println(
    Thread.currentThread().getName()
);

Main Thread

Every Java application starts with a thread that executes the main() method.

This is commonly called the main thread.

Example

public class HelloWorld {
 
    public static void main(String[] args) {
 
        System.out.println(
            Thread.currentThread().getName()
        );
    }
}

Typical output:

main

So a simple Java application already has at least one thread: the main thread.

Creating Multiple Threads

We can create multiple thread objects.

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 3; i++) {
 
            System.out.println(
                Thread.currentThread().getName()
                + " : "
                + i
            );
        }
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
 
        thread1.setName("Thread-1");
        thread2.setName("Thread-2");
 
        thread1.start();
        thread2.start();
    }
}

The output order can vary because the threads are independently scheduled.

For example:

Thread-1 : 1
Thread-2 : 1
Thread-2 : 2
Thread-1 : 2
Thread-1 : 3
Thread-2 : 3

Another execution may produce a different order.

Thread Scheduling

When multiple threads are running, the JVM and underlying operating system determine when each thread gets execution time.

Therefore, you should generally not assume a specific execution order between independently running threads.

For example:

thread1.start();
thread2.start();

does not guarantee:

Thread-1
Thread-2

in that exact execution order.

The scheduler may allow either thread to execute first or alternate between them.

Thread.sleep()

The sleep() method pauses the currently executing thread for approximately the specified duration.

Example

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 5; i++) {
 
            System.out.println(i);
 
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Here, Thread.sleep(1000) requests a pause of approximately 1000 milliseconds, or 1 second.

Important Point

sleep() affects the currently executing thread.

It does not cause the thread to permanently stop.

After the sleep duration expires, the thread becomes eligible to continue execution.

InterruptedException

The Thread.sleep() method can throw InterruptedException.

A common approach is:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

Restoring the interrupt status is important when the interruption should be propagated to code higher in the call chain.

Thread.join()

The join() method allows one thread to wait for another thread to finish.

Example

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 3; i++) {
 
            System.out.println(i);
 
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Now:

class MyThread extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 3; i++) {
 
            System.out.println(i);
 
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args)
        throws InterruptedException {
 
        MyThread thread = new MyThread();
 
        thread.start();
 
        thread.join();
 
        System.out.println(
            "Main thread continues"
        );
    }
}

The main thread waits until thread terminates before continuing.

Simple idea:

Main Thread
    |
    | start
    ↓
Worker Thread
    |
    | completes
    ↓
Main Thread continues

Thread.isAlive()

The isAlive() method checks whether a thread has been started and has not yet terminated.

Example

MyThread thread = new MyThread();
 
System.out.println(thread.isAlive());
 
thread.start();
 
System.out.println(thread.isAlive());

The result can depend on the timing of execution, especially if the thread finishes very quickly.

Generally:

Before start()     → false
While running     → true
After termination → false

Thread.getState()

The getState() method returns the current state of a thread.

Example

Thread thread = new Thread();
 
System.out.println(thread.getState());

A newly created thread that has not been started is typically:

NEW

Java Thread States

A Java thread can be in one of these Thread.State states:

  • NEW
  • RUNNABLE
  • BLOCKED
  • WAITING
  • TIMED_WAITING
  • TERMINATED

1. NEW

The thread object has been created but start() has not been called.

Thread thread = new Thread();

State: NEW

2. RUNNABLE

After calling:

thread.start();

the thread enters the RUNNABLE state.

This state represents a thread that is ready to run or is running under the JVM's scheduling model.

3. BLOCKED

A thread enters BLOCKED when it is waiting to acquire a monitor lock, typically to enter a synchronized block or method.

4. WAITING

A thread enters WAITING when it waits indefinitely for another thread to perform an action.

Examples include certain uses of Object.wait() and Thread.join() without a timeout.

5. TIMED_WAITING

A thread enters TIMED_WAITING when it waits for a specified amount of time.

Examples include Thread.sleep(1000); and thread.join(1000);.

6. TERMINATED

The thread has completed execution.

For example, after the run() method finishes, the thread eventually reaches TERMINATED.

A terminated thread cannot be started again.

Thread Priority

Java provides thread priority through setPriority() and getPriority().

Example

Thread thread = new Thread();
 
thread.setPriority(Thread.MAX_PRIORITY);
 
System.out.println(
    thread.getPriority()
);

Java defines these constants:

  • Thread.MIN_PRIORITY
  • Thread.NORM_PRIORITY
  • Thread.MAX_PRIORITY

Their standard values are:

MIN_PRIORITY  = 1
NORM_PRIORITY = 5
MAX_PRIORITY  = 10

Important Point

Thread priority should not be treated as a guarantee that one thread will always execute before another. Actual scheduling depends on the JVM and operating system.

Interrupting a Thread

Java provides interrupt() to request that a thread be interrupted.

Example

thread.interrupt();

An interrupt is a cooperative mechanism. It does not forcibly terminate the thread.

For example, if a thread is sleeping:

try {
    Thread.sleep(5000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

the sleep can be interrupted.

The thread's interrupt status can also be checked using:

Thread.currentThread().isInterrupted()

Can a Thread Be Started Twice?

No. A thread object can be started only once.

For example:

MyThread thread = new MyThread();
 
thread.start();
 
thread.start();

The second call results in:

IllegalThreadStateException

If another execution is required, create a new thread object.

MyThread thread1 = new MyThread();
thread1.start();
 
MyThread thread2 = new MyThread();
thread2.start();

Thread Constructor

The Thread class provides several constructors.

Some commonly used forms include:

Thread() — Creates a thread with default settings.

Thread(String name) — Creates a thread with a specified name.

Thread(Runnable target) — Creates a thread associated with a Runnable task.

Thread(Runnable target, String name) — Creates a thread with a Runnable task and a specified name.

Example

Thread thread =
    new Thread("Worker");
 
thread.start();

Thread Using Runnable

Although this page focuses on the Thread class, an important alternative is implementing Runnable.

class MyTask implements Runnable {
 
    @Override
    public void run() {
        System.out.println(
            "Task is running"
        );
    }
}

Then:

Thread thread =
    new Thread(new MyTask());
 
thread.start();

This approach separates the task from the thread that executes it.

It is often preferable to extending Thread, especially when the class already needs to extend another class.

Thread vs Runnable

ThreadRunnable
Thread is a classRunnable is an interface
Class extends ThreadClass implements Runnable
Cannot extend another class at the same timeCan still extend another class
Combines task and thread objectSeparates task from thread
Useful for simple examplesOften preferred for reusable task definitions

Example using Thread:

class MyThread extends Thread {
 
    @Override
    public void run() {
        // task
    }
}

Example using Runnable:

class MyTask implements Runnable {
 
    @Override
    public void run() {
        // task
    }
}

Thread Daemon

Java also supports daemon threads.

A daemon thread is a background thread that does not keep the JVM alive by itself once all non-daemon threads have terminated.

Example

Thread thread = new Thread(() -> {
 
    while (true) {
        System.out.println("Background work");
 
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            break;
        }
    }
});
 
thread.setDaemon(true);
thread.start();

setDaemon(true) must be called before the thread is started.

thread.setDaemon(true);

After a thread has started, its daemon status cannot be changed.

Thread Example: Performing Two Tasks

class TaskOne extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 5; i++) {
 
            System.out.println(
                "Task One: " + i
            );
        }
    }
}
 
class TaskTwo extends Thread {
 
    @Override
    public void run() {
 
        for (int i = 1; i <= 5; i++) {
 
            System.out.println(
                "Task Two: " + i
            );
        }
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        TaskOne taskOne = new TaskOne();
        TaskTwo taskTwo = new TaskTwo();
 
        taskOne.start();
        taskTwo.start();
    }
}

The two tasks can execute concurrently, and their output order is not guaranteed.

Important Thread Methods

MethodPurpose
start()Starts a new thread of execution
run()Contains the thread's task
sleep()Pauses the currently executing thread for a specified duration
join()Waits for another thread to terminate
interrupt()Requests interruption of a thread
isInterrupted()Checks the thread's interrupt status
isAlive()Checks whether a thread is alive
currentThread()Returns the currently executing thread
getName()Returns thread name
setName()Sets thread name
getPriority()Gets thread priority
setPriority()Sets thread priority
getState()Gets current thread state
setDaemon()Sets daemon status before start
isDaemon()Checks whether thread is a daemon

Common Mistakes with Thread

Mistake 1: Calling run() Instead of start()

Incorrect when the intention is to start a new thread:

thread.run();

Correct:

thread.start();

Mistake 2: Starting the Same Thread Twice

Incorrect:

thread.start();
thread.start();

A thread object can only be started once.

Mistake 3: Assuming Thread Execution Order

Do not assume:

thread1.start();
thread2.start();

means thread1 will always finish before thread2.

The actual execution order is affected by thread scheduling.

Mistake 4: Using sleep() as Synchronization

Thread.sleep() pauses execution for a period of time. It should not generally be used as a replacement for proper thread coordination or synchronization.

Thread Class vs ExecutorService

For learning the fundamentals of Java threads, the Thread class is important.

However, in larger applications, manually creating many threads can become difficult to manage.

Java provides higher-level concurrency APIs such as ExecutorService.

For example:

ExecutorService executor =
    Executors.newFixedThreadPool(5);

These APIs allow applications to manage reusable worker threads and submit tasks without manually creating a new Thread for every task.

Key Takeaway

The Java Thread class represents a thread of execution and provides methods for starting, monitoring, interrupting, and coordinating threads.

The most important concepts to remember are:

Thread
  ↓
start()
  ↓
New thread of execution
  ↓
run()
  ↓
Task execution

Remember the most important distinction:

thread.start();

starts a new thread, while:

thread.run();

is simply a normal method call. For modern application development, understanding Thread provides the foundation for learning more advanced Java concurrency features such as Runnable, ExecutorService, synchronization, locks, Future, CompletableFuture, and concurrent collections.

See you in next page....🙂

← OverviewRunnable Interface →
← OverviewRunnable Interface →