简体   繁体   English

包含Thread成员的Runnable对象有什么问题吗?

[英]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? Thread是否是传递给Thread的Runnable成员的事实? 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? 对于奖励积分,在Runnable的构造函数中调用.start()是否重要?

The idea of Runnable is to seperate the what needs to be done from the actual thread/execution component. Runnable的想法是分离实际线程/执行组件需要完成的工作 By mixing both you don't get any benefit from using Runnable (except not using your extends slot ) 通过混合两者,您不会从使用Runnable获得任何好处(除了不使用您的扩展槽

In your case extending Thread and overriding run() would get you the same result. 在你的情况下,扩展Thread并重写run()会得到相同的结果。

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: 您可以创建第二个Runnable类来从主类调用,例如:

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: 如果Runnable只在该上下文中使用,只要Runnable类不需要公开,这可以变得更简单:

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() . Runnable ,只需调用Thread.currentThread()

For your bonus question, there's no need to call start() from the constructor, or even from main() . 对于你的奖金问题,不需要从构造函数调用start() ,甚至不需要从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. 如果您希望程序在程序启动后立即运行,则这两个选项都是选项,但在某些情况下,您可能更愿意先等待用户输入并从其他方法调用start()

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. 如果同步很重要,请考虑使用线程池

It works. 有用。

But that a reeeeeaaally bad practice 但这是一种非常糟糕的做法

There is absolutely no point in doing this because the thread you are running in is always accessable from Thread.currentThread() . 这样做绝对没有意义,因为您运行的线程始终可以从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();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM