Series index: Java Intermediate/Advanced Programming: article index
Disclaimer up front: everything in this series is my own understanding of the subject, typed out by hand. It may well contain mistaken views or misunderstandings. Use it as reference only, and corrections are welcome.
Last time we talked broadly about why we need multiple threads. Now that we want to study concurrency, let’s create threads ourselves and dig into its mysteries.
All demo code for this series is public at https://github.com/renfei/demo/tree/master/java/ConcurrentDemo
The Thread Class
Most tutorials tell you to extend Thread. What I want to add is that I keep stressing how everything in Java is an object — and really understanding that makes things click much faster. A thread is an object too, and Thread is the class of thread objects.
Let’s feel it in code first, and then I’ll walk you through the relationship between Thread and Runnable.
First, extend Thread and override run(), adding a constructor that takes a name so the thread can print its own name and an incrementing counter ten times:
class MyThread extends Thread {
private String myName;
public MyThread(String name) {
this.myName = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(this.myName + " :: printing i = " + i);
}
}
}
Then instantiate three threads and give them names:
Thread threadA = new MyThread("Thread A");
Thread threadB = new MyThread("Thread B");
Thread threadC = new MyThread("Thread C");
Now start them. Careful: call start(), not run()! run() isn’t meant for you to call — it’s there for the scheduler. Call run() directly and you don’t get multithreading; you just execute in the current thread. Beginners, watch out for this one.
threadA.start();
threadB.start();
threadC.start();
And there you have concurrent execution — you’ll see three threads interleaving their output in the console. Full source for this one: https://github.com/renfei/demo/blob/master/java/ConcurrentDemo/src/main/java/net/renfei/demo/concurrent/ThreadDemo.java. Besides Thread, we also need Runnable.
The Runnable Interface
Java allows only single inheritance but multiple interface implementations, which makes interfaces the more flexible choice. Implementing Runnable is the other way to write multithreaded code.
Implement Runnable and override run(), again with a name-taking constructor so the thread prints its name and ten incrementing numbers:
class MyThread implements Runnable {
private String myName;
public MyThread(String name) {
this.myName = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(this.myName + " :: printing i = " + i);
}
}
}
Instantiate three threads — this time passing in classes that implement Runnable — and give them names:
Thread threadA = new Thread(new MyThread("Thread A"));
Thread threadB = new Thread(new MyThread("Thread B"));
Thread threadC = new Thread(new MyThread("Thread C"));
Start them the same way:
threadA.start();
threadB.start();
threadC.start();
The upside is you can implement as many interfaces as you like, instead of being stuck extending the single Thread class. Full source: https://github.com/renfei/demo/blob/master/java/ConcurrentDemo/src/main/java/net/renfei/demo/concurrent/RunnableDemo.java
Thread Class vs. Runnable Interface
The two examples above look very similar, so what’s the actual relationship? Here’s the class diagram:

And to make it concrete, here’s the key part of the source:
public class Thread implements Runnable {
private Runnable target;
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
So Thread implements Runnable, and the run() we override is really Runnable’s run().
Wrapping Up
By now the relationship between Thread and Runnable should be clear. As I keep repeating, everything in Java is an object: Thread is the thread object, and it holds an object implementing Runnable.
My own way of putting it: Thread is the thread, Runnable is your business logic. Thread’s fields give you state, names and other attributes; Thread’s methods give you ways to operate on the thread.
