在 Java 中,当我们 return 来自正在进行的 Future 线程的函数时会发生什么?

In Java, what happens when we return from a function with Future threads in progress?

我想知道当我们不等待 Future Tasks 完成并 return 之前会发生什么? 未来的任务是否仍然完成,或者一旦我 return 从函数中杀死所有线程。 例如:

@AllArgsConstructor
public class IdGenerator() {
    private DBPersister dbPersister;
    public String generateId(){
        String id = UUID.randomString();
        Future<Void> persistIdInDB =  dBPersister.persist(id);
        return id;
    }    
}

我想 return ID 生成后立即发送到下游,不想等待将其存储在数据库中。 return 从函数中调用是否会终止函数中创建的所有未来任务?还是我可以放心,函数dbPersister.persist一旦调用就会完全执行?如果没有,我有什么办法可以在 Java 中实现相同的目标吗?

从您的方法返回时,您可以确定的是:

  • dBPersister.persist(id); 将被调用
  • 当前线程不会阻塞,因为您没有在 Future<Void>
  • 上调用 get

持久化具体会发生什么只能通过查看dBPersister.persist(id);的实现来发现,以及持久化是否由于环境变量(例如数据库宕机等)而成功

Future只是一个接口。这取决于各个实现如何提供方法 cancel()get()isCancelled()done().

例如,您可以编写一个 returns 一个 Future 同步完成工作的方法:

    public Future<Void> print(String x) {
        System.out.println(message);
        return new Future<Void>() {
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                return false;
            }

            @Override
            public boolean isCancelled() {
                return false;
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public Void get() throws InterruptedException, ExecutionException {
                return null;
            }

            @Override
            public Void get(long timeout, TimeUnit unit)
                    throws InterruptedException, ExecutionException, TimeoutException {
                return null;
            }
        };
    }

同样,您可以编写自己的实现,它在调用 get() 之前不会执行工作! (这不是多线程上下文中的好代码,但它说明了这一点):

 public Future<Void> foo(String x) {
        return new Future<Void>() {

            private boolean done = false;

            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                return false;
            }

            @Override
            public boolean isCancelled() {
                return false;
            }

            @Override
            public boolean isDone() {
                return done;
            }

            @Override
            public Void get() throws InterruptedException, ExecutionException {
                System.out.println(message);
                done = true;
                return null;
            }

            @Override
            public Void get(long timeout, TimeUnit unit)
                    throws InterruptedException, ExecutionException, TimeoutException {
                return get();
            }
        };
    }

DBPersister 要么来自第三方库,要么是你自己的。我们无法猜测它是如何实现的 Future.

returns Future 的一个主流例子是 ExecutorService。一个典型的 ExecutorService 将保持 运行 直到有东西调用它的 shutdown(),然后它将停止接受新任务,处理其队列中的内容,然后终止。在最后一个线程完成之前,JVM 不会停止。

然而,Runtime.exit()有可能突然杀死一切。避免调用它;或者,如果您无法避免,请了解关闭挂钩。