这是对部分构造的对象的引用转义吗?

时间:2014-11-15 03:28:52

标签: java concurrency java-8 future

我想在给定的类上运行CompletableFuture属性。如果我已经像这样初始化,那会是危险的并且可能会创建一个部分构造的对象吗?

public class MyClass { 

    public final CompletableFuture<BigDecimal> myExpensiveVal = CompletableFuture.supplyASync(() -> calculateExpensiveMethod(this));

//...
}

1 个答案:

答案 0 :(得分:1)

CompletableFuture.supplyASync将提供的Supplier发送到另一个帖子,当然是,如果此供应商对您正在构建的实例有任何引用,则会泄漏{{ 1}}这使得一个不完整的对象实例对其他线程可见,甚至使任何this出版物保证无效。

在这种特殊情况下,很明显你可以重复发现这种逃逸:

final

public class EscapingThis { public final CompletableFuture<BigDecimal> myExpensiveVal = CompletableFuture.supplyAsync(() -> calculateExpensiveMethod(this)); final int fourtyTwo; public EscapingThis() { System.out.println(Thread.currentThread()+" starts creating "+this); try { myExpensiveVal.get(); } catch (InterruptedException|ExecutionException ex) { Logger.getLogger("EscapingThis").log(Level.SEVERE, null, ex); } System.out.println("still incomplete"); fourtyTwo=42; System.out.println("leaving constructor"); } static BigDecimal calculateExpensiveMethod(EscapingThis instance) { System.out.println(Thread.currentThread() +" says: hello incomplete instance "+instance); System.out.println("fourtyTwo = "+instance.fourtyTwo); return BigDecimal.ONE; } public static void main(String... arg) { new EscapingThis(); } } hello incomplete instance EscapingThis@1a9515 之前,您会看到fourtyTwo = 0still incomplete 。但您甚至可能会在leaving constructor消息后看到Thread[main,5,main] starts creating …消息,因为时间未定义。

请注意,如果hello incomplete …是实例方法,则不需要calculateExpensiveMethod参数来让实例泄漏。对将调用实例方法的this的隐含引用也是一个泄漏引用。