Java 在自己的构造函数中调用thread.start()

Java 在自己的构造函数中调用thread.start(),java,multithreading,Java,Multithreading,线程在自己的构造函数中调用此.start()合法吗?如果是的话,这会导致哪些潜在问题?我知道,在构造函数运行到完成之前,对象不会完全初始化,但除此之外还有其他问题吗 这是合法的,但不明智。实例的线程部分将完全初始化,但构造函数可能不会初始化。几乎没有理由扩展线程,像这样的技巧对代码没有帮助。我假设您希望这样做以减少代码的冗长;而不是说 Thread t = new CustomThread(); t.start(); activeThreads.add(t); 你可以说 activeThrea

线程在自己的构造函数中调用此.start()合法吗?如果是的话,这会导致哪些潜在问题?我知道,在构造函数运行到完成之前,对象不会完全初始化,但除此之外还有其他问题吗

这是合法的,但不明智。实例的线程部分将完全初始化,但构造函数可能不会初始化。几乎没有理由扩展线程,像这样的技巧对代码没有帮助。

我假设您希望这样做以减少代码的冗长;而不是说

Thread t = new CustomThread();
t.start();
activeThreads.add(t);
你可以说

activeThreads.add( new CustomThread() );
我也喜欢少说些冗长的话,但我同意其他受访者的看法,即你不应该这样做。具体来说,它违反了公约;任何熟悉Java并阅读第二个示例的人都会认为线程尚未启动。更糟糕的是,如果他们编写自己的线程代码,并以某种方式与您的线程进行交互,那么一些线程将需要调用
start
,而其他线程则不需要

当你独自工作时,这可能看起来不那么令人信服,但最终你将不得不与其他人一起工作,养成良好的编码习惯是很好的,这样你就可以轻松地与其他人一起工作,并使用标准约定编写代码


然而,如果你不在乎惯例,讨厌多余的冗长,那就去吧;这不会导致任何问题,即使您多次尝试错误地调用
start

顺便说一句,如果您希望降低详细程度,并且仍然保持构造函数的“标准”语义,可以创建工厂方法:

activeThreads.add( CustomThread.newStartedThread() );
这是“合法的”,但我认为最重要的问题是: 一个班级应该做一件事并且把它做好

如果您的类在内部使用线程,则该线程的存在不应在公共API中可见。这允许在不影响公共API的情况下进行改进。解决方案:扩展可运行的,而不是线程

如果您的类提供了一般功能,而在本例中,这些功能恰好在线程中运行,那么您不希望将自己限制为始终创建线程。这里的解决方案也是一样:扩展Runnable,而不是线程


为了不太详细,我支持使用工厂方法(例如Foo.createAndRunInThread())的建议。

出于内存安全原因,您不应该将对对象的引用或该对象的字段从其构造函数中公开给另一个线程。假设您的自定义线程具有实例变量,通过从构造函数中启动它,可以保证违反Java内存模型准则。有关更多信息,请参阅。

如果线程类进一步子类化,您还将看到wierd问题。在这种情况下,一旦super()退出,线程就会运行,子类在其构造函数中可能执行的任何操作都可能无效

@比尔·巴克斯代尔 如果线程已经在运行,再次调用start会得到一个非法的ThreadStateException,您不会得到2个线程。

合法。。。是(其他地方提到了注意事项)。明智的没有

我只是一种你很容易避免的气味。如果你想让你的线程自动启动,就这样做吧

公共类ThreadCreationTest{
公共静态void main(字符串[]args)引发InterruptedException{
创建的最终AtomicInteger线程=新的AtomicInteger(0);
while(true){
最终倒计时闩锁=新倒计时闩锁(1);
新线程(){

{start();}//对此答案的评论?没有错误。向下投票?如果您认为这是错误的,请定位一个源代码。这是正确的。答案根本不是固定的。除非您使用可运行构造函数,否则您可以在构造函数完成之前从
线程#运行
中引用
,这违反了内存安全规则。因此,您一定要小心。在仔细阅读了这个问题后,我意识到这是关于在同一线程的构造函数中调用start的。我想象了一个不同的场景,虽然我的场景围绕着这里讨论的问题工作,但它们与这个问题的上下文无关。请接受我的道歉。一点也不担心。我很高兴我们解决了这个问题我担心我误解了一些基本的东西。:)这与OP的问题有什么关系?
public class ThreadCreationTest {
  public static void main(String[] args) throws InterruptedException {
    final AtomicInteger threads_created = new AtomicInteger(0);
    while (true) {
      final CountDownLatch latch = new CountDownLatch(1);
      new Thread() {
        { start(); } // <--- Like this ... sweet and simple.
        public void run() {
          latch.countDown();
          synchronized (this) {
            System.out.println("threads created: " +
                threads_created.incrementAndGet());
            try {
              wait();
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
          }
        }
      };
      latch.await();
    }
  }
}