我正在尝试使用CompletableFuture
从方法执行异步调用。完成该任务后,我尝试打印对象DummyObject的值,这些值对于调用Async调用的方法而言是本地的。
我想知道它如何运作? 3秒钟后,线程(myThread
)死了,并且DummyObject不在范围内,那么thenAccept中的Async回调仍在打印正确的值。线程是否锁定了DummyObject?还是正在发生其他事情?
请注意,我只是在尝试模拟一个场景。所以我正在使用Thread.stop()
。
编辑-问题是有关thenAccept Consumer如何处理范围的?请保持与此相关的答案。
以下程序的输出:
Starting Async stuff
Thread Alive? false
Reached Main end and waiting for 8 more seconds
James T. Kirk
United Federation of Planets
AsyncTest.java
public class AsyncTest {
public static void main(String args[]) {
Thread myThread = new Thread() {
@Override
public void run() {
DummyObject dummyObj = new DummyObject();
dummyObj.setObjectName("James T. Kirk");
dummyObj.setObjectNationality("United Federation of Planets");
System.out.println("Starting Async stuff");
new AsyncTaskExecuter().executeAsync().thenAccept(taskStatus -> {
if(taskStatus.booleanValue()) {
System.out.println(dummyObj.getObjectName());
System.out.println(dummyObj.getObjectNationality());
}
});
}
};
myThread.start();
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread.stop();
System.out.println("Thread Alive? "+ myThread.isAlive());
System.out.println("Reached Main end and waiting for 8 more seconds");
try {
Thread.sleep(8 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class AsyncTaskExecuter {
public CompletableFuture<Boolean> executeAsync() {
return (CompletableFuture<Boolean>) CompletableFuture.supplyAsync(this::theTask);
}
public Boolean theTask() {
try {
Thread.sleep(6 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}
class DummyObject {
private String objectName;
private String objectNationality;
// getters and setters
}
最佳答案
就您所要讨论的内容而言,dummyObj
变量仍在传递给thenAccept
的lambda范围内。
实际上,带有原始变量的堆栈框架将消失。但是,Java编译器会安排代表lambda的对象具有保存在只读合成变量中的原始变量值的副本(即对DummyObject
实例的引用)。
(这是限制的原因,即如果该变量有效地是最终变量,则lambda只能在封闭方法中使用局部变量。如果该变量有效地是最终变量,则可以将其值复制到另一个最终变量,而不会造成任何不一致的风险更改中的变量。)
无论如何,lambda通过综合变量使用DummyObject
。只要lambda可达,DummyObject
实例将保持可达。