Threads and Runnable
Create and manage threads using Thread and Runnable to execute code concurrently.
Overview
Key Points
- •Runnable: implement void run() and pass to new Thread(runnable)
- •Thread subclass: extend Thread and override run()
- •thread.start() creates a new thread; thread.run() calls run() on the current thread (not concurrent)
- •thread.join() waits for the thread to finish before continuing
- •thread.sleep(milliseconds) pauses the current thread
- •Thread.currentThread() returns the currently executing thread
- •Threads share heap memory; each thread has its own stack
- •The main method runs in the main thread; spawned threads run in parallel
Examples
Creating threads with Runnable and lambda
public class Main {
public static void main(String[] args) throws InterruptedException {
// Using Runnable (anonymous class)
Runnable task1 = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("Task1: " + i + " on " + Thread.currentThread().getName());
}
}
};
// Using lambda (cleaner)
Runnable task2 = () -> {
for (int i = 0; i < 3; i++) {
System.out.println("Task2: " + i + " on " + Thread.currentThread().getName());
}
};
Thread t1 = new Thread(task1, "worker-1");
Thread t2 = new Thread(task2, "worker-2");
t1.start();
t2.start();
// Wait for both to finish
t1.join();
t2.join();
System.out.println("Both threads done");
}
}Output order between t1 and t2 is non-deterministic: the JVM scheduler decides. Always call start() not run(). join() ensures main() waits for threads to complete before exiting.
Thread lifecycle: sleep and state
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread counter = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Count: " + i);
try {
Thread.sleep(100); // pause 100ms
} catch (InterruptedException e) {
System.out.println("Thread interrupted!");
return; // exit thread on interrupt
}
}
}, "counter");
System.out.println("State before start: " + counter.getState()); // NEW
counter.start();
System.out.println("State after start: " + counter.getState()); // RUNNABLE or TIMED_WAITING
counter.join();
System.out.println("State after join: " + counter.getState()); // TERMINATED
}
}Thread.sleep() throws InterruptedException if the thread is interrupted while sleeping. Always handle it: either stop the thread or restore the interrupt flag with Thread.currentThread().interrupt().
Parallel computation: splitting work across threads
public class Main {
static long sumRange(long start, long end) {
long sum = 0;
for (long i = start; i <= end; i++) sum += i;
return sum;
}
public static void main(String[] args) throws InterruptedException {
long total = 100_000_000L;
long mid = total / 2;
long[] results = new long[2];
Thread t1 = new Thread(() -> results[0] = sumRange(1, mid));
Thread t2 = new Thread(() -> results[1] = sumRange(mid + 1, total));
long startTime = System.currentTimeMillis();
t1.start();
t2.start();
t1.join();
t2.join();
long elapsed = System.currentTimeMillis() - startTime;
System.out.println("Sum: " + (results[0] + results[1]));
System.out.println("Time: " + elapsed + "ms");
}
}Sharing an array between threads (results[0] and results[1]) is safe here because each thread writes to a different index. Concurrent writes to the same index would require synchronization.
Common Mistakes
- Calling thread.run() instead of thread.start(). run() executes on the calling thread without creating a new thread. Only start() spawns a new thread
- Not calling join() when you need the thread to finish before using its results. Without join(), you may read results before the thread writes them
- Catching InterruptedException and doing nothing with it. At minimum, re-throw or restore the interrupt flag: Thread.currentThread().interrupt()
Note
For simple concurrent tasks, prefer ExecutorService (covered in the next topic) over managing Thread objects directly. ExecutorService handles thread pooling, lifecycle, and result collection more cleanly.
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4