Threads and Runnable — Thread Class, Runnable, Callable, Thread States, and Daemon Threads
In this tutorial, you will learn about Threads and Runnable. We cover key concepts, practical examples, and best practices to help you master this topic.
Java threads enable concurrent execution within a single Process, with the Thread class and Runnable interface providing the foundation. A thread is the smallest unit of execution — multiple threads share the same memory space but execute independently, making them powerful but also dangerous when accessing shared data.
What You'll Learn
- Creating threads with Thread class and Runnable
- Thread states: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
- Callable for returning values and throwing exceptions
- Daemon vs user threads
Why It Matters
Understanding threads is essential for building responsive applications. A GUI that freezes during file loading is using threads incorrectly. A server that cannot handle multiple clients is using threads incorrectly. Threads are the foundation of all concurrency.
Real-World Use
Web servers use thread pools to handle requests. GUIs use a separate thread for background tasks. Batch processors parallelize work across threads.
Creating Threads
Extending Thread
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Running in: " + Thread.currentThread().getName());
}
}
MyThread t = new MyThread();
t.start(); // starts a new thread
// Never call run() directly — that runs in the calling thread
Implementing Runnable
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running in: " + Thread.currentThread().getName());
}
}
Thread t = new Thread(new MyRunnable());
t.start();
Lambda Syntax
Thread t = new Thread(() -> {
System.out.println("Lambda thread running");
});
t.start();
The Thread Lifecycle
A thread goes through six states:
- NEW — created with
new Thread()but not started - RUNNABLE — after
start(), eligible for CPU scheduling - BLOCKED — waiting to acquire a monitor lock
- WAITING — waiting indefinitely for another thread (wait/join/park)
- TIMED_WAITING — waiting for a specified time (sleep/wait(timeout)/join(timeout))
- TERMINATED — execution completed
Thread t = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE
Thread.sleep(100);
System.out.println(t.getState()); // TIMED_WAITING (probably)
t.join();
System.out.println(t.getState()); // TERMINATED
Callable and Future
Runnable cannot return a value or throw checked exceptions. Callable fixes both:
Callable<Integer> task = () -> {
Thread.sleep(1000);
return 42;
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(task);
// Get the result (blocks until done)
Integer result = future.get();
System.out.println(result); // 42
executor.shutdown();
Future Methods
future.get(); // blocks until done
future.get(1, TimeUnit.SECONDS); // blocks with timeout
future.isDone(); // non-blocking check
future.cancel(true); // attempt to cancel
Daemon Threads
Daemon threads run in the background and do not prevent the JVM from exiting:
Thread daemon = new Thread(() -> {
while (true) {
System.out.println("Daemon running...");
try { Thread.sleep(1000); } catch (InterruptedException e) { break; }
}
});
daemon.setDaemon(true);
daemon.start();
// JVM exits after main thread finishes, even if daemon is still running
Use cases: background Garbage Collection, monitoring, auto-save.
Thread Methods
Thread t = new Thread(task);
t.start(); // begin execution
t.join(); // wait for thread to finish
t.join(1000); // wait with timeout
t.setName("worker"); // name for debugging
t.setPriority(Thread.MAX_PRIORITY); // not reliable across platforms
t.interrupt(); // request interruption
Thread.sleep(1000); // static: current thread sleeps
Thread.yield(); // static: hint to scheduler
Common Mistakes
- Calling
run()instead ofstart(). This runs the method in the current thread, not a new thread. - Starting a thread twice. Once a thread is started and terminated, it cannot be restarted.
- Using
Thread.stop(). It is deprecated because it releases all monitors, potentially leaving shared data in an inconsistent state. - Ignoring
InterruptedException. Catching and ignoring it swallows the interruption request. Restore the interrupt flag:Thread.currentThread().interrupt(). - Using threads directly instead of thread pools. Creating threads is expensive. Use
ExecutorServicefor production code.
Practice Questions
1. What is the difference between start() and run() on a Thread?
start() creates a new thread and calls run() in that thread. run() executes in the calling thread — no new thread is created.
2. What are the six thread states?
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
3. What is the difference between Runnable and Callable?
Runnable returns void and cannot throw checked exceptions. Callable returns a value and can throw checked exceptions.
4. What is a daemon thread?
A background thread that does not prevent the JVM from exiting. The JVM shuts down when only daemon threads remain.
5. Why is Thread.stop() deprecated?
It releases all monitors, leaving shared data in an inconsistent state. Use interrupt() instead.
Challenge Question:
Write a program that calculates the sum of a large array (10 million integers) using multiple threads. Divide the array into equal parts, create a Callable for each part, submit to an ExecutorService, collect Futures, and sum the results. Compare the time with a single-threaded version.
FAQ
Mini Project
Write a program ThreadDemo.java that:
- Creates 5 threads using different approaches (extends Thread, implements Runnable, lambda, anonymous class)
- Each thread prints its name, priority, and state
- Uses
join()to wait for all threads to finish - Creates a daemon thread that runs in the background
- Uses
CallableandFutureto compute a value - Demonstrates thread states by printing state transitions
- Shows proper interruption handling
What's Next
Multiple threads accessing shared data need coordination. Lesson 52 covers synchronization — the synchronized keyword, volatile, atomic classes, and the happens-before relationship.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro