【问题标题】:Java safe publication in constructor, avoiding leaking "this" reference构造函数中的 Java 安全发布,避免泄漏“this”引用
【发布时间】:2017-08-09 19:57:18
【问题描述】:

我希望对下面的代码是否完全线程安全并且不会泄漏“this”引用提供一些意见?我要做的基本上是使用 ExecutorService 在后台线程中引导/初始化另一个服务。

我只是有点担心,因为我从某个地方读到从构造函数启动线程是不好的做法,因为它会在类完全构造之前泄漏“this”引用。

public class MyService {

private final ExecutorService executorService;
private volatile AnotherService anotherService;
private volatile boolean isReady = false;


public MyService(final ExecutorService executorService) {
    this.executorService = executorService;
    start();
}

private void start() {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                anotherService = init();
                isReady = true;
            } catch (Exception e) {
                // do nothing, just retry later
            }
        }
    });
}

private AnotherService init() {
    // some code to initialize
    return AnotherServiceBootstrap.getInstance().bootstrap();
}

// some other methods in class

}

非常感谢!

【问题讨论】:

  • 您是否担心您可能会同时在两个线程中创建 MyService 的两个实例,而其中一个或两个实例最终可能会使用来自错误线程的 executorService?
  • 我认为这种事情过于复杂和不必要。你知道你会打电话给那个服务吗?然后在您创建的对象的每个实例中创建或注入服务引用。这一切有什么好处?
  • 您应该使用AtomicBoolean 而不是volatile boolean 在这里解释stackoverflow.com/a/3787435/6138873
  • @PaulHicks 不,这不是这里关心的问题,关心的是是否存在将未完全初始化的 MyService 对象的“this”引用泄漏到另一个线程的情况
  • 您应该与其他服务交谈。他们不应该设计难以使用的东西。世界正朝着 REST 微服务的方向发展。它们应该 100% 准备好使用。如果您不得不担心“引导”,那么他们做错了。

标签: java multithreading concurrency thread-safety


【解决方案1】:

我认为您的代码没有任何风险 -

  1. 请参考this question
  2. 鉴于该帖子中的解释,您面临的唯一风险是,如果有人可以在构造函数退出之前访问唯一的最终成员 (executorService)。但是,以这种方式访问​​该变量的唯一位置是在您正在创建并提交给执行程序服务的线程中。在 submit() 方法运行之前,你会得到一个发生前的保证,它表示你的构造函数到目前为止所做的所有更改都发生在提交的线程运行之前。所以我相信你已经被覆盖了。

【讨论】:

    猜你喜欢
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 2018-11-18
    • 2014-07-30
    相关资源
    最近更新 更多