如何中断CompletableFuture :: join?

时间:2017-05-28 19:48:34

标签: java multithreading java-8 interrupt completable-future

我发现CompletableFuture::join在未完成时似乎不间断

// CompletableFuture::join implementation from JDK 8 sources
public T join() { 
    Object r;
    return reportJoin((r = result) == null ? waitingGet(false) : r);
}

在上面的实现中,waitingGet(false)将忽略工作Thread的中断标志并继续等待。我想知道如何打断Thread CompletableFuture::join

3 个答案:

答案 0 :(得分:7)

如果您想支持中断,请不要使用module.exports = function(req, res) { let formidable = require('formidable'); let form = new formidable.IncomingForm(); form.parse(req, (err, fields, files) => { let readStream = fs.createReadStream(files.uploadedfile.path); let ffmpeg = require('fluent-ffmpeg') let ffmpegCmd = ffmpeg(readStream) ... }); }); ,而是使用join()。基本上它们是相同的,除了:

  • get()仅在join()中定义,而CompletableFuture来自接口get()
  • Future包含join()中的例外情况,而CompletionException将其包含在get()
  • ExecutionException可能会被中断,然后会抛出get()

请注意,您中断的是InterruptedException,而不是Thread。例如,以下代码在等待Future

时中断主线程
myFuture.get()

输出:

CompletableFuture<Void> myFuture = new CompletableFuture<>();
Thread mainThread = Thread.currentThread();
CompletableFuture.runAsync(() -> {
    try {
        Thread.sleep(1000);
        System.out.println("Interrupting…");
        mainThread.interrupt();
        Thread.sleep(1000);
        System.out.println("Completing");
        myFuture.complete(null);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
try {
    myFuture.get();
    System.out.println("Get succeeded");
} catch (Exception e) {
    System.out.println("Get failed");
    e.printStackTrace();
}

如果您将Interrupting… Get failed java.lang.InterruptedException at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:347) at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895) at CompletableFutureInteruption.main(CompletableFutureInteruption.java:37) … 替换为get(),则中断确实无效。

答案 1 :(得分:2)

我终于放弃了在等待CompletableFuture::join完成时阻塞的线程。

相反,我使用CompletableFuture::allof来获取CompletableFuture 所有,当我所有加入的期货结束时结束。然后在工作线程中调用 all Future的get()方法。当get()返回时,我会通过迭代所有已加入的期货来收集我的所有结果,并在其上调用getNow。这样的程序是可以中断的。

答案 2 :(得分:0)

我最后清楚地知道你实际上正在寻找可中断的,但作为一种解决方法可以被例外打断如下(尽管它是join()):

private static void testCompleteExceptionally() {
    String name = "Hearen";
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        delay(500L);
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    });

    if (name != null) {
        completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
    }
    out.println(completableFuture.handle((s, t) ->  s != null ? s : "Hello, Stranger!" + t.toString()).join());
}