Constructing Threads and Runnables

In our Java threading introduction, we created a thread in two steps:

There are actually a couple of variations on this pattern of thread construction that we'll look at here.

Pattern 1: create an explicit class that implements Runnable

The Runnable implementations that we created were inline classes. That is, we didn't spell out a full class declaration. But strictly speaking, the way to create a Runnable— or rather, a class that implements the Runnable interface— is as follows:

public class MyTask implements Runnable {
  public void run() {
    ...
  }
}
...
Runnable r = new MyTask();
Thread thr = new Thread(r);

If we just write new Runnable(), the compiler under the hood actually creates a "dummy class" of the above form for us. But sometimes it's useful to create our own class. In our simultaneous message printing example, both Runnables essentially had similar code: only the message and time interval differed. So it would be neater to define a class that took the message and interval as parameters to the constructor:

public class MessagePrinter implements Runnable {
  private final String message;
  private final long interval;
  public MessagePrinter(String msg, long interval) {
    this.message = msg;
    this.interval = interval;
  }
  public void run() {
    try {
      while (true) {
        System.out.println(message);
        Thread.sleep(interval);
      }
    } catch (InterruptedException iex) {}
  }
}

Notice that for reasons we'll come to, we declare the variables final. This is basically a means of making sure they are "seen properly" by the two threads involved (the thread that constructs the object, then the thread in which run() will actually be running when we start the thread).

Pattern 2: override Thread.run()

You can actually dispense with the separate Runnable method. The Thread class has a (normally empty) run() method. If you don't pass in a Runnable to the constructor, then the run() method of Thread will be called instead when the thread starts. So we could write something like this:

public void MyThread extends Thread {
  public void run() {
    ...
  }
}
...
Thread thr = new MyThread();
thr.start();

Of course, we can also turn this into an inline class:

Thread thr = new Thread() {
  public void run() {
    ...
  }
}
thr.start();

Which thread construction pattern?

So, which method should you use to construct a thread in Java? In general, constructing a separate Runnable gives you more flexibility. Running in a Thread turns out not to be the only way of running a Runnable, so if you embed everything inside a Thread object from the beginning, you may end up with more code to change later on if you decide to do things differently. In the simplest case, having a separate Runnable allows you to write code such as the following:

public void runTask(Runnable r, boolean separateThread) {
  if (separateThread) {
    (new Thread(r)).start();
  } else {
    r.run();
  }
}

Other instances where a Runnable is used are with the Swing.invokeLater() method (called from a non-Swing thread to ask Swing to run a particular task in its UI thread), or with various executor utilities introduced in the Java 5 concurrency package.

On the other hand, for threads representing fairly "major" tasks running right through your application, where it's clear from the ground up that you don't need the flexibility of the separate Runnable object, just overriding Thread.run() may make your code a little less cluttered.

Next

Now that you habe learnt about the basics of starting a thread, you should get familiar with the following:


If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.