sigmabeta
sigmabeta

Reputation: 1184

Is there anything wrong with a Runnable object containing a Thread member?

Consider the following object:

public class Mindblower implements Runnable {

    private Thread ownThread;        

    @Override
    public void run() {
        // do all the things
    }

    public Mindblower() {
        ownThread = new Thread(this);
        ownThread.start();
    }
}

Does this work? Will the fact that the Thread is a member of the Runnable being passed to the Thread matter? It seems to me like it should work, but thinking about it makes my head hurt as if I was watching a Christopher Nolan movie.

For bonus points, does it matter if .start() is called within the Runnable's constructor?

Upvotes: 0

Views: 160

Answers (4)

Nathaniel Jones
Nathaniel Jones

Reputation: 1849

Yes, it works, but you might want to consider a few other ways to accomplish this and make your code easier to understand. You could create a second Runnable class to call from your main class, for instance:

public class Mindblower {

  public static void main(String[] args) {
    Thread ownThread = new Thread(new MindblowingRunnable());
    ownThread.start();

    // Other stuff that you want done concurrently on the main thread
  }

  private class MindblowingRunnable implements Runnable {
    @Override
    public void run() {
      // Stuff to be carried out in your thread
    }
  }
}

This can be made a little simpler if the Runnable will only be used in that context, so long as the Runnable class need not be public:

public class Mindblower {

  public static void main(String[] args) {
    Thread ownThread = new MindblowingThread();
    ownThread.start();

    // Other stuff that you want done concurrently on the main thread
  }

  private class MindblowingThread extends Thread {
    @Override
    public void run() {
      // Stuff to be carried out in your thread
    }
  }
}

While you can keep a local reference to a thread, this is only useful if you need to interrupt it from your main thread. From within the Runnable, just call Thread.currentThread().

For your bonus question, there's no need to call start() from the constructor, or even from main(). Both of these are options if you want your thread to run as soon as your program starts, but in some cases you may prefer to wait for user input first and call start() from some other method.

All of this assumes that you are only creating a single thread, or that if there are multiple threads, that synchronization between them is not an issue for your program. If synchronization matters, consider a Thread Pool instead.

Upvotes: 1

OldCurmudgeon
OldCurmudgeon

Reputation: 65813

There is absolutely no point in doing this because the thread you are running in is always accessable from Thread.currentThread().

Also - if you want to auto-start you should use something like this but this is still not advisable. A user of your class may want to do other things before starting your thread.

public class Mindblower implements Runnable {

  @Override
  public void run() {
    // You can access your thread at any time - you can even interrupt yourself.
    Thread.currentThread().interrupt();
  }

  public Mindblower() {
    // Do not start here.
  }

  {
    // A more acceptable way of having a self-starting thread but still not a good idea.
    new Thread(this).start();
  }
}

Upvotes: 0

micha
micha

Reputation: 49572

The idea of Runnable is to seperate the what needs to be done from the actual thread/execution component. By mixing both you don't get any benefit from using Runnable (except not using your extends slot)

In your case extending Thread and overriding run() would get you the same result.

Upvotes: 1

Philipp Sander
Philipp Sander

Reputation: 10249

It works.

But that a reeeeeaaally bad practice

Upvotes: 0

Related Questions