java 在自己的构造函数中调用 thread.start()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/84285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
calling thread.start() within its own constructor
提问by Heath Borders
is it legal for a thread to call this.start() inside its own constructor? and if so what potential issues can this cause? I understand that the object wont have fully initialized until the constructor has run to completion but aside from this are there any other issues?
线程在自己的构造函数中调用 this.start() 是否合法?如果是这样,这会导致什么潜在问题?我知道在构造函数运行完成之前对象不会完全初始化,但除此之外还有其他问题吗?
回答by Heath Borders
For memory-safety reasons, you shouldn't expose a reference to an object or that object's fields to another thread from within its constructor. Assuming that your custom thread has instance variables, by starting it from within the constructor, you are guaranteed to violate the Java Memory Model guidelines. See Brian Goetz's Safe Construction Techniquesfor more info.
出于内存安全的原因,您不应从其构造函数中向另一个线程公开对对象或该对象字段的引用。假设您的自定义线程具有实例变量,通过从构造函数中启动它,您肯定会违反 Java 内存模型准则。有关更多信息,请参阅Brian Goetz 的安全施工技术。
回答by John Gardner
You will also see wierd issues if the Thread class is ever further subclassed. In that case, you'll end up with the thread running already once the super() exits, and anything the subclass might do in its constructor could be invalid.
如果 Thread 类被进一步子类化,您还会看到奇怪的问题。在这种情况下,一旦 super() 退出,您就会结束线程已经运行,并且子类在其构造函数中可能做的任何事情都可能无效。
@bill barksdale If the thread is already running, calling start again gets you an IllegalThreadStateException, you don't get 2 threads.
@bill barksdale 如果线程已经在运行,再次调用 start 会给你一个 IllegalThreadStateException,你不会得到 2 个线程。
回答by Eli Courtwright
I assume that you want to do this to make your code less verbose; instead of saying
我假设您想这样做是为了让您的代码不那么冗长;而不是说
Thread t = new CustomThread();
t.start();
activeThreads.add(t);
you can just say
你可以说
activeThreads.add( new CustomThread() );
I also like having less verbosity, but I agree with the other respondents that you shouldn't do this. Specifically, it breaks the convention; anyone familiar with Java who reads the second example will assume that the thread has not been started. Worse yet, if they write their own threading code which interacts in some way with yours, then some threads will need to call startand others won't.
我也喜欢不那么冗长,但我同意其他受访者的意见,你不应该这样做。具体来说,它打破了惯例;任何熟悉 Java 的人在阅读第二个示例时都会假设该线程尚未启动。更糟糕的是,如果他们编写自己的线程代码并以某种方式与您的线程交互,那么某些线程将需要调用start而其他线程则不需要。
This may not seem compelling when you're working by yourself, but eventually you'll have to work with other people, and it's good to develop good coding habits so that you'll have an easy time working with others and code written with the standard conventions.
当您自己工作时,这似乎并不引人注目,但最终您将不得不与其他人一起工作,养成良好的编码习惯是件好事,这样您就可以轻松地与他人合作并使用标准约定。
However, if you don't care about the conventions and hate the extra verbosity, then go ahead; this won't cause any problems, even if you try to call startmultiple times by mistake.
但是,如果您不关心约定并且讨厌多余的冗长,那么请继续;这不会导致任何问题,即使您尝试start错误地多次调用。
回答by millenomi
By the way, if one wants lower verbosity and still keep the constructor with its "standard" semantics, one could create a factory method:
顺便说一句,如果想要更低的冗长性并且仍然保持构造函数的“标准”语义,则可以创建一个工厂方法:
activeThreads.add( CustomThread.newStartedThread() );
回答by volley
It is"legal", but I think the most important issue is this: A class should do one thing and do it well.
它是“合法的”,但我认为最重要的问题是:一个班级应该做一件事并做好。
If your class uses a thread internally, then the existence of that thread should not be visible in the public API. This allows improvement without affecting the public API. Solution: extend Runnable, not Thread.
如果您的类在内部使用线程,则该线程的存在不应在公共 API 中可见。这允许在不影响公共 API 的情况下进行改进。解决方案:扩展 Runnable,而不是 Thread。
If your class provides general functionality which, in this case, happens to run in a thread, then you don't want to limit yourself to alwayscreating a thread. Same solution here: extend Runnable, not Thread.
如果您的类提供一般功能,在这种情况下,恰好在线程中运行,那么您不希望限制自己总是创建一个线程。相同的解决方案:扩展 Runnable,而不是 Thread。
For less verbosity I second the suggestion to use a factory method (e.g. Foo.createAndRunInThread()).
为了不那么冗长,我建议使用工厂方法(例如 Foo.createAndRunInThread())。
回答by Tom Hawtin - tackline
It's legal, but not wise. The Thread part of the instance will be completely initialised, but your constructor may not. There is very little reason to extend Thread, and to pull tricks like this isn't going to help your code.
这是合法的,但不明智。实例的 Thread 部分将被完全初始化,但您的构造函数可能不会。几乎没有理由扩展 Thread,并且使用这样的技巧对您的代码没有帮助。
回答by OldCurmudgeon
Legal ... yes (with caveats as mentioned elsewhere). Advisable ... no.
合法......是的(有别处提到的警告)。建议...不。
I's just a smell you can only too easily avoid. If you want your thread to auto-start, just do it like Heinz Kabutz.
我只是一种你很容易避免的气味。如果你想让你的线程自动启动,就像Heinz Kabutz 一样。
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();
}
}
}

