我想在给定的类上运行CompletableFuture属性。如果我已经像这样初始化,那会是危险的并且可能会创建一个部分构造的对象吗?
public class MyClass {
public final CompletableFuture<BigDecimal> myExpensiveVal = CompletableFuture.supplyASync(() -> calculateExpensiveMethod(this));
//...
}
答案 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 = 0
和still incomplete
。但您甚至可能会在leaving constructor
消息后看到Thread[main,5,main] starts creating …
消息,因为时间未定义。
请注意,如果hello incomplete …
是实例方法,则不需要calculateExpensiveMethod
参数来让实例泄漏。对将调用实例方法的this
的隐含引用也是一个泄漏引用。