首页 > 解决方案 > 如果它具有发生前的保证,那么在构造函数的最后一个语句中让“this”转义是否安全?

问题描述

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

但是将任务提交给执行者会提供发生前发生的保证,如此所述。那么在构造函数的最后一条语句中提交任务会不会好呢?或者更一般的问题:如果构造函数的最后一个语句提供发生前的保证,那么让“this”在构造函数的最后一个语句中转义是否安全?

标签: javaconcurrency

解决方案


Stefan Feuerhahn的答案是正确的。

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

通常,我们希望在设计中遵循单一责任原则。一个类应该有一个单一的目的,并且应该尽量不偏离那个狭窄的特定目的。

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

这种运行报告的时间安排与应用程序的生命周期相关。对于一件重要的事情,执行器服务最终必须在不再需要或应用程序退出时关闭。否则后备线程池可能会像僵尸一样无限期地继续下去。您的报告生成类不应该知道何时不再需要它,也不应该知道应用程序何时或为何退出。

问题的另一个方面是配置执行器服务涉及了解部署方案。多少 RAM、多少 CPU 内核、主机上的其他负担,都有助于决定如何设置 executor 服务。您的报告生成代码不应该因为部署情况的变化而改变。

生成报告的类不应该知道调用应用程序的生命周期,也不应该知道执行器服务。生成报告的应用程序应该只知道如何生成一份报告。代码中的其他位置,可能是某个报表管理器类或应用程序的生命周期编排代码,应该处理运行报表的频率和时间。


推荐阅读