← Back to Advanced Java Course | Chapter 2: Multithreading | Lesson 3 of 8

Java Runnable Interface

What is the Runnable Interface?

The Runnable interface is a functional interface in Java used to represent a task that a thread can execute. It defines a single abstract run() method containing the statements that should run in the background, independent of how that task actually gets scheduled onto a thread.

Example: What is the Runnable Interface?

java
public class Main {
	static class Task implements Runnable {
		public void run() {
			System.out.println("Task executing");
		}
	}
	public static void main(String[] args) {
		new Task().run();
	}
}

Implementing Runnable

To implement Runnable, use the implements keyword on your class and provide a body for its run() method. This separates 'what work needs to happen' from 'how it gets executed', since the same Runnable object can be handed to a Thread, an ExecutorService, or anything else that knows how to run one.

Example: Implementing Runnable

java
public class Main {
	static class PrintTask implements Runnable {
		public void run() {
			System.out.println("Work happens here");
		}
	}
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new PrintTask());
		t.start();
		t.join();
	}
}

Creating Threads with Runnable

To actually run a Runnable task, pass your task instance into the Thread constructor rather than extending Thread directly. This creates a Thread object that simply wraps and delegates to your Runnable's run() method when start() is called.

Example: Creating Threads with Runnable

java
public class Main {
	public static void main(String[] args) throws InterruptedException {
		Runnable task = () -> System.out.println("Runnable passed to Thread");
		Thread t = new Thread(task);
		t.start();
		t.join();
	}
}

Lambda Expressions with Runnable

Since Runnable is a functional interface with exactly one abstract method, you can write compact thread declarations using a lambda expression instead of a full class. This removes the boilerplate of writing an anonymous inner class just to define a single run() body.

Example: Lambda Expressions with Runnable

java
public class Main {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(() -> System.out.println("Lambda instead of anonymous class"));
		t.start();
		t.join();
	}
}

Thread vs. Runnable

Implementing Runnable is generally preferred over extending Thread directly, because Java classes can only extend one parent class. Implementing an interface instead leaves your class free to still extend some other class if it ever needs to, which extending Thread would have ruled out.

Example: Thread vs. Runnable

java
public class Main {
	static class Worker extends Thread {
		public void run() { System.out.println("Extends Thread -- can't extend anything else"); }
	}
	static class Job implements Runnable {
		public void run() { System.out.println("Implements Runnable -- free to extend another class"); }
	}
	public static void main(String[] args) throws InterruptedException {
		new Worker().start();
		new Thread(new Job()).start();
	}
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.