Java “出租”安全吗;这";在构造函数的最后一个语句中转义,如果它发生在保证之前?

Java “出租”安全吗;这";在构造函数的最后一个语句中转义,如果它发生在保证之前?,java,concurrency,Java,Concurrency,Java中的一个常见问题是在对象构造期间不让“this”引用转义,因此不在构造函数中启动任何线程。但我发现自己编写了很多类,这些类应该使用执行器启动线程。根据常见的建议,我应该编写一个额外的start()方法,将任务提交给执行者 但将任务提交给执行者会在有文件记录的担保之前发生。那么,在构造函数的最后一个语句中提交任务可以吗?或者更一般的问题:如果构造函数的最后一个语句提供的“this”发生在保证之前,那么在该语句中转义“this”是否安全?是的,这是安全的,因为提供保证之前的语句将确保所有字段

Java中的一个常见问题是在对象构造期间不让“this”引用转义,因此不在构造函数中启动任何线程。但我发现自己编写了很多类,这些类应该使用执行器启动线程。根据常见的建议,我应该编写一个额外的start()方法,将任务提交给执行者


但将任务提交给执行者会在有文件记录的担保之前发生。那么,在构造函数的最后一个语句中提交任务可以吗?或者更一般的问题:如果构造函数的最后一个语句提供的“this”发生在保证之前,那么在该语句中转义“this”是否安全?

是的,这是安全的,因为提供保证之前的语句将确保所有字段都正确初始化,其他线程可见。需要注意的是,子类可能会破坏这种安全性,因此最好将类设置为最终类。但是,正如霍尔格所指出的那样,即使在那时,一个额外的构造函数授权给启动线程的构造函数也可能会损害安全性

“不要让它从构造函数中逃逸”的一般建议之所以存在,主要是因为遵循这条规则更容易,因此不太容易出错,然后记住所有细微差别(如子类化)。

这是正确的

我将补充一个建议,即在执行工作的类中嵌入执行器服务可能是一种“代码气味”,表明设计薄弱

一般来说,我们希望在设计中遵循这些原则。一个类应该有一个单一的目的,并且不应该偏离那个狭隘的特定目的

例如,如果编写一个类来创建报告,那么该类应该只知道该报告。该类不应该知道什么时候应该运行该报告,或者运行报告的频率,或者如果报告已经运行,其他代码关心什么


运行报告的时间安排与应用程序的生命周期有关。重要的一点是,executor服务最终必须在不再需要或应用程序退出时关闭。否则,支持线程池可能会像僵尸一样无限期地继续下去,不仅在创建子类时会被破坏,而且在有人向启动线程的构造函数添加另一个委托构造函数时也会被破坏。当子类被排除在外时,提供一个静态工厂方法并强制类的用户编写
Type.create(…)
而不是
new Type(…)
。这没有什么害处。好的,但是“报表管理器”可能必须启动一个线程。所以考虑问题是关于报告经理。在大多数情况下,在构造函数中启动线程/执行器几乎肯定是错误的方法。在大多数情况下,在构造时使用对象几乎肯定是错误的方法。我同意在构造函数完成后启动线程更安全(例如,在静态工厂方法中)。但我不同意在创建对象时创建线程是不好的风格。我经常发现,如果一个对象一旦创建就已经启动,并且不需要显式调用start方法,那么类就更容易使用。因此,只需创建一个ReportManager(然后关闭它)。