簡體   English   中英

使用CompletableFuture時如何避免此編譯器警告關閉OutputStream?

[英]How to avoid this compiler warning to close an OutputStream when using CompletableFuture?

我正在使用CompletableFuture進行異步操作,以下載文件並通過OutputStream保存其內容。 以下作品的代碼,但是編譯器給我一個警告,要么使用try-with-resources或關閉OutputStreamfinally-clause ,但未來在完成后關閉whenComplete

碼:

final OutputStream outputStream = Files.newOutputStream(file.toPath());
final String url = "https://example.com/some-download.zip";
final CompletionStage<WSResponse> futureResponse = this.client
        .url(url)
        .setMethod("GET")
        .stream();

futureResponse.thenCompose(res -> {
    downloadTask.setTotalBytes(res);
    Source<ByteString, ?> responseBody = res.getBodyAsSource();

    Sink<ByteString, CompletionStage<akka.Done>> outputWriter =
            Sink.foreach(bytes -> {
                downloadTask.addReceivedBytes(bytes.size());
                System.out.println(downloadTask.getProgressAsString());
                outputStream.write(bytes.toArray());
            });

    return responseBody.runWith(outputWriter, this.materializer);
}).whenComplete((res, error) -> {
    try {
        outputStream.close();
    } catch (final IOException e) {
        e.printStackTrace();
    }
});

警告:

在此處輸入圖片說明

問題:

當我使用try-with-resources ,由於CompletableFuture的異步特性不會阻塞,因此程序OutPutStream在將任何內容寫入文件之前關閉OutPutStream

那么,有沒有一種方法可以在CompletionStage聲明OutputStream並將其向下傳遞呢?

@AndyTurner在其評論中的建議是正確的。 我只需要稍微調整一下代碼即可使其工作。

我沒有意識到responseBody.runWith()返回另一個CompletionStage ,因此使用try-with-resourcesfinallythenComponse塊中關閉了OutputStream ,所以返回的CompletionStage (來自responseBody.runWith() )無法寫入它了。 這導致了錯誤。 因此,我們只需使用.toCompletableFuture().get()在同一個塊中“同步”處理responseBody.runWith() .toCompletableFuture().get() 這沒問題,因為該塊本身在另一個線程中運行,即保持異步狀態。 由於我們不再返回任何內容,因此我們還需要使用thenAccept (接受一個Consumer而不是thenCompose (接受一個Function

final String url = "https://example.com/some-download.zip";
final CompletionStage<WSResponse> futureResponse = this.client
        .url(url)
        .setMethod("GET")
        .stream();

futureResponse
        .thenAccept(res -> {
            try (OutputStream outputStream = Files.newOutputStream(file.toPath())) {
                downloadTask.setTotalBytes(res);
                Source<ByteString, ?> responseBody = res.getBodyAsSource();

                Sink<ByteString, CompletionStage<akka.Done>> outputWriter =
                        Sink.foreach(bytes -> {
                            downloadTask.addReceivedBytes(bytes.size());
                            System.out.println(downloadTask.getProgressAsString());
                            outputStream.write(bytes.toArray());
                        });
                responseBody.runWith(outputWriter, this.materializer).toCompletableFuture().get();
            } catch (IOException | InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM