Java Threads
Separate a task from when it executes.
Read this topic in தமிழ் ↗.
By the end of this lesson, you can…
- Explain the key idea behind Threads.
- Read and run a complete example, then predict what changes.
- Recognize the topic-specific mistake discussed below.
Understand the idea
A thread can execute independently of the calling thread. start schedules a new thread; calling run directly is just a normal method call on the current thread. Use join when the caller must wait for completion. Real shared-state work also needs correct synchronization.
Explore the details
Java Threads
Threads allows a program to operate more efficiently by doing multiple things at the same time.
Threads can be used to perform complicated tasks in the background without interrupting the main program.
Creating a Thread
There are two ways to create a thread.
It can be created by extending the Thread class and overriding its run()
method:
Another way to create a thread is to implement the Runnable interface:
Running Threads
If the class extends the Thread class, the thread can be run by creating an instance of the
class and call its start() method:
If the class implements the Runnable interface, the thread can be run by passing an
instance of the class to a Thread object's constructor and then calling the thread's
start() method:
Differences between "extending" and "implementing" Threads
The major difference is that when a class extends the Thread class, you cannot extend any other class, but by implementing the Runnable interface,
it is possible to extend from another class as well, like: class MyClass extends OtherClass implements Runnable.
Concurrency Problems
Because threads run at the same time as other parts of the program, there is no way to know in which order the code will run. When the threads and main program are reading and writing the same variables, the values are unpredictable. The problems that result from this are called concurrency problems.
Three Ways to Create a Thread
// Way 1 — Extend Thread class
class MyThread extends Thread {
public void run() {
System.out.println("Thread running: " + getName());
}
}
new MyThread().start();
// Way 2 — Implement Runnable (preferred — allows extending other classes)
class MyTask implements Runnable {
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}
new Thread(new MyTask()).start();
// Way 3 — Lambda (Java 8+, most concise)
new Thread(() -> System.out.println("Lambda thread!")).start();Thread Lifecycle
| State | Description | How to reach it |
|---|---|---|
| NEW | Thread created but not yet started | new Thread(task) |
| RUNNABLE | Ready to run (waiting for CPU time) | thread.start() |
| RUNNING | Currently executing run() | JVM scheduler selects it |
| BLOCKED/WAITING | Paused — waiting for lock or another thread | sleep(), wait(), join() |
| TERMINATED | run() method has finished | Normal completion or exception |
start() vs run(): Always call start() — it creates a new thread and calls run() on it. Calling run() directly just executes the method on the current thread — no new thread is created.
To avoid concurrency problems, it is best to share as few attributes between threads as
possible. If attributes need to be shared, one possible solution is to use the isAlive()
method of the thread to check whether the thread has finished running before using any
attributes that the thread can change.
A complete runnable example
This complete Main.java program focuses on the lesson idea. Reference fragments above may demonstrate individual statements; this example includes the imports, entry point, and supporting types it needs.
public class Main {
public static void main(String[] args) throws Exception {
Thread worker = new Thread(() -> System.out.println("Worker finished"));
worker.start();
worker.join();
System.out.println("Main continues");
}
}Predict first. Then reveal the expected output / வெளியீடு
Worker finished Main continues
The output shown was checked by running this complete example. Trace the executed statements in order, then compare with your run.
Change it. Run it. Understand it.
Load this lesson example into the editor. Change one value or statement, predict the result, then press RUN to execute Java.
Powered by OneCompiler. Code you run is sent to OneCompiler for execution. For Scanner examples, supply input in the editor I/O panel; for file examples, files exist in its execution environment.
Make it your own
Practice challenge
Remove join and run several times. What output order is guaranteed?
Reveal the answer and reasoning / விடை
Without join, either line can appear first. One particular run does not establish a guaranteed order.
One mistake to avoid: Thread.sleep is not a reliable replacement for coordination such as join, locks, or higher-level concurrency utilities.
Your learning checkpoint
- Explain the example without reading the output first.
- Make the change requested in the practice task.
- Describe why the result changed—or why compilation failed.
Ready to move on? Follow the next lesson in course order, or return to the curriculum to review a prerequisite.