我正在尝试使用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实例将保持可达。

10-06 13:42