Java 包含线程成员的可运行对象有什么问题吗?

Java 包含线程成员的可运行对象有什么问题吗?,java,multithreading,Java,Multithreading,考虑以下对象: public class Mindblower implements Runnable { private Thread ownThread; @Override public void run() { // do all the things } public Mindblower() { ownThread = new Thread(this); ownThread.

考虑以下对象:

public class Mindblower implements Runnable {

    private Thread ownThread;        

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

    public Mindblower() {
        ownThread = new Thread(this);
        ownThread.start();
    }
}
这行吗?线程是传递给线程的Runnable的成员这一事实是否重要?在我看来,这似乎应该奏效,但想到这一点,我的头就痛了,就像我在看克里斯托弗·诺兰的电影一样

对于奖励积分,在Runnable的构造函数中调用
.start()
是否重要?

它可以工作


但是一个非常糟糕的做法是将需要执行的操作与实际的线程/执行组件分离开来。将两者混合使用,您不会从使用
Runnable
中获得任何好处(除了不使用扩展槽)


在您的情况下,扩展
线程
并重写
运行()
将得到相同的结果。

这样做毫无意义,因为您运行的线程始终可以从
线程.currentThread()
访问

此外,如果你想自动启动,你应该使用这样的东西,但这仍然是不可取的。类的用户可能希望在启动线程之前执行其他操作

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();
  }
}

是的,它是有效的,但是您可能需要考虑其他一些方法来实现这一点,使您的代码更容易理解。您可以创建第二个

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
    }
  }
}
如果
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
    }
  }
}
虽然可以保留对线程的本地引用,但这仅在需要从主线程中断线程时才有用。在
Runnable
中,只需调用
Thread.currentThread()

对于您的额外问题,不需要从构造函数调用
start()
,甚至不需要从
main()
调用。如果希望线程在程序启动后立即运行,则这两个选项都是可选的,但在某些情况下,您可能更希望先等待用户输入,然后从其他方法调用
start()


所有这些都假设您只创建一个线程,或者如果有多个线程,那么它们之间的同步对您的程序来说不是问题。如果同步问题很重要,请考虑A。

而不是思考这么难,为什么不运行它,看看会发生什么?线程化!不,但它应该有用。。。我认为O.O.关于构造函数的
start()
:这是一个bug!它可能导致多线程问题。当
这个
从构造函数转义到另一个线程时,许多并发保证(例如
最终
字段的可见性)就消失了。在您的例子中,
被传递给构造函数中的
线程
对象,然后启动该
线程
对象,使它从另一个线程访问
this.run
——这构成了
this
this
的构造函数中泄漏到另一个线程。这或多或少是我在寻找的,所以如果您将其作为答案提交,我将接受它。@RohitJain+1如果这不是关于多线程的。不幸的是,它是。我同意,它似乎不是一个好主意,可能不是我会做的事情。我关心的是,这是否会机械地导致问题(一些疯狂的递归堆栈溢出或类似的事情)。没有递归的东西。这或多或少是我的处理方法。OP中的问题是一对what-if,这个答案解决了这两个问题。谢谢