Creating Threads
In Java, threads enable concurrent execution within a single process. Java provides two primary ways to create threads, plus modern executor-based approaches used in production systems. This is a high-frequency interview topic.
Ways to Create Threads in Java
- Extend Thread class
- Implement Runnable interface
- Implement Callable (Executor framework) (advanced/modern)
1️⃣ Creating a Thread by Extending Thread Class
How It Works
- Create a subclass of Thread
- Override the
run()method - Call
start()to begin execution
Example
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); // starts new thread
}
}
Important Rules
run()contains the thread logicstart()creates a new call stack- Calling
run()directly ❌ does NOT create a new thread
Limitations
- Java does not support multiple inheritance
- Class cannot extend any other class
2️⃣ Creating a Thread by Implementing Runnable (Most Preferred)
How It Works
- Implement Runnable
- Pass object to Thread constructor
- Call
start()
Example
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args) {
Thread t = new Thread(new MyTask());
t.start();
}
}
Why Runnable Is Preferred (Interview Point)
- Supports multiple inheritance
- Separates task from thread
- Better object-oriented design
- Widely used in frameworks
3️⃣ Creating Thread Using Lambda (Java 8+)
Thread t = new Thread(() -> {
System.out.println("Thread using lambda");
});
t.start();
- ✔ Clean
- ✔ Modern
- ✔ Uses Runnable internally
4️⃣ Creating Threads Using Callable (Executor Framework)
Used when:
- Thread must return a value
- Thread may throw checked exceptions
Callabletask = () -> 10 + 20; ExecutorService service = Executors.newSingleThreadExecutor(); Future result = service.submit(task); System.out.println(result.get()); service.shutdown();
- ✔ Production-ready
- ✔ Controlled thread management
start() vs run() (Very Important)
| Method | Behavior |
|---|---|
start() |
Creates new thread |
run() |
Executes like normal method |
t.run(); // ❌ no new thread
t.start(); // ✔ new thread
Thread Naming (Good Practice)
Thread t = new Thread(new MyTask(), "Worker-1");
t.start();
Thread Priority (Hint)
t.setPriority(Thread.MAX_PRIORITY);
⚠ Priority is scheduler-dependent
Comparison: Thread vs Runnable (Interview Favorite)
| Aspect | Thread | Runnable |
|---|---|---|
| Inheritance | Extends Thread | Implements Runnable |
| Multiple inheritance | ❌ No | ✔ Yes |
| Code separation | ❌ Poor | ✔ Good |
| Recommended | ❌ Less | ✔ More |
Best Practices (Real-World)
- Prefer Runnable / Callable over extending Thread
- Use ExecutorService for thread management
- Avoid manual thread creation in large systems
- Name threads meaningfully
- Do not override
start()
Common Beginner Mistakes
- Calling
run()instead ofstart() - Extending Thread unnecessarily
- Creating too many threads
- Ignoring thread lifecycle
- Not shutting down executors
Interview-Ready Answers
Short Answer
Threads can be created by extending the Thread class or implementing Runnable.
Detailed Answer
In Java, threads can be created by extending the Thread class or implementing the Runnable interface. Implementing Runnable is preferred because it supports multiple inheritance and separates task logic from thread management. Modern applications use the Executor framework with Runnable or Callable for better scalability.
Key Takeaway
Runnable for design.
Thread for execution.
Executor for production.
Mastering thread creation is the foundation for safe, scalable, and efficient Java concurrency.