首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我可以从构造函数启动线程吗?

我可以从构造函数启动线程吗?
EN

Stack Overflow用户
提问于 2009-05-11 21:26:12
回答 3查看 519关注 0票数 3

给定J5+内存模型(JSR-133),下面的代码是线程安全的并且是允许的吗?

如果它是安全的,在某些情况下是可以接受的吗?

代码语言:javascript
复制
public final class BackgroundProcessor
extends Object
implements Runnable
{

public BackgroundProcessor(...) {
    super();

    ...

    new Thread(this).start();
    }

public void run() {
    ...
    }
}

在我阅读新的JMM规范时,启动线程会与启动的线程所做的任何事情创建一种发生之前的关系。

假设该对象具有在构造函数中设置并在run()中使用的私有成员变量。

并且该类被标记为期末,以防出现子类意外。

注意:这里有一个类似的问题,但这个问题有不同的角度:calling thread.start() within its own constructor

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-05-12 03:23:09

好吧,除非您特别想在Java并发问题上与Brian Goetz意见相左,否则我认为这是错误的。虽然他的原话是“最好不要……”,但我还是听从了他的建议。来自JCIP,第42页:

“在构造期间可以让‘’引用转义的常见错误是从构造函数启动线程...在构造函数中创建线程没有什么问题,但最好不要立即启动线程。相反,公开一个或initialize方法...”

更新:只是为了详细说明为什么这是一个问题。尽管在对Thread.start()的调用和线程的run()方法实际开始执行之间肯定存在内存屏障,但是在调用Thread.start()之后构造函数期间发生的事情之间没有这种屏障。因此,如果还需要设置一些其他变量,或者如果JVM执行一些“刚刚构造的对象”的内务管理,那么这两个变量都不能保证被其他线程看到:即处于不完整状态的其他线程可以看到该对象。

顺便说一句,除了它是否真的破坏了JMM之外,它还让人感觉有点像构造函数中的一件“奇怪的事情”。

票数 3
EN

Stack Overflow用户

发布于 2009-05-11 22:55:17

JLS: Threads and Locks

两个操作可以按发生之前的关系排序。如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作是可见的,并且排序在第二个动作之前。

如果我们有两个动作x和y,我们写hb(x,y)来表明x发生在y之前。

  • 如果x和y是同一线程的动作,并且在程序顺序中x在y之前,则hb(x,y)。

对线程的start()调用发生在启动的线程中的任何操作之前。

因此,我们可以得出结论,在调用Thread.start()之前,构造函数中的所有操作都发生在启动的线程中的所有操作之前。如果Thread.start()毕竟是对对象字段的所有写操作,那么启动的线程将看到对对象字段的所有写操作。如果没有对字段的其他写入(另一个线程将读取),则代码是线程安全的。

票数 4
EN

Stack Overflow用户

发布于 2009-05-11 21:34:11

Runnable

  • 你的类应该实现

  • 是的,你的代码是OK

  • 扩展Object是不必要的。我相信您知道该对象是由所有类隐式扩展的。我不知道这种显式扩展对象的流行做法是从哪里来的,但这是一种糟糕的风格。
票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/850160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档