异步编程 - AWS SDK for Java 1.x

我们宣布了即将推出 end-of-support 的 AWS SDK for Java (v1)。建议您迁移到 AWS SDK for Java v2。有关日期、其他详细信息以及如何迁移的信息,请参阅链接的公告。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

异步编程

您可以使用同步异步方法来调用对 AWS 服务的操作。同步方法会阻止执行您的线程,直到客户端接收到服务的响应。异步方法会立即返回,并控制调用的线程,而不必等待响应。

由于异步方法在收到响应之前返回,所以需要通过某种方法在响应准备就绪时接收响应。 AWS SDK for Java 提供了两种方法:F uture 对象回调方法

Java Futures

中的异步方法 AWS SDK for Java 返回一个 F ut ure 对象,该对象包含将来异步操作的结果。

调用 Future isDone() 方法,确定该服务是否已提供响应对象。当响应准备好时,可以通过调用 Future get() 方法来获取响应对象。在应用程序继续处理其他任务时,可使用该机制定期轮询异步操作的结果。

以下是一个异步操作的示例,该异步操作调用 Lambda 函数,接收Future可以容纳InvokeResult对象的函数。InvokeResult 对象仅在 isDone()true 时可检索到。

import com.amazonaws.services.lambda.AWSLambdaAsyncClient; import com.amazonaws.services.lambda.model.InvokeRequest; import com.amazonaws.services.lambda.model.InvokeResult; import java.nio.ByteBuffer; import java.util.concurrent.Future; import java.util.concurrent.ExecutionException; public class InvokeLambdaFunctionAsync { public static void main(String[] args) { String function_name = "HelloFunction"; String function_input = "{\"who\":\"SDK for Java\"}"; AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient(); InvokeRequest req = new InvokeRequest() .withFunctionName(function_name) .withPayload(ByteBuffer.wrap(function_input.getBytes())); Future<InvokeResult> future_res = lambda.invokeAsync(req); System.out.print("Waiting for future"); while (future_res.isDone() == false) { System.out.print("."); try { Thread.sleep(1000); } catch (InterruptedException e) { System.err.println("\nThread.sleep() was interrupted!"); System.exit(1); } } try { InvokeResult res = future_res.get(); if (res.getStatusCode() == 200) { System.out.println("\nLambda function returned:"); ByteBuffer response_payload = res.getPayload(); System.out.println(new String(response_payload.array())); } else { System.out.format("Received a non-OK response from {AWS}: %d\n", res.getStatusCode()); } } catch (InterruptedException | ExecutionException e) { System.err.println(e.getMessage()); System.exit(1); } System.exit(0); } }

异步回调

除了使用 Java Future 对象监控异步请求的状态外,SDK 还允许您实现使用该AsyncHandler接口的类。 AsyncHandler提供了两种根据请求完成方式调用的方法:onSuccessonError

回调接口方法的主要优势是它让您无需轮询 Future 对象即可确定请求是否已完成。相反,您的代码能够立即开始其下一个活动,并由开发工具包在适当时调用处理程序。

import com.amazonaws.services.lambda.AWSLambdaAsync; import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder; import com.amazonaws.services.lambda.model.InvokeRequest; import com.amazonaws.services.lambda.model.InvokeResult; import com.amazonaws.handlers.AsyncHandler; import java.nio.ByteBuffer; import java.util.concurrent.Future; public class InvokeLambdaFunctionCallback { private class AsyncLambdaHandler implements AsyncHandler<InvokeRequest, InvokeResult> { public void onSuccess(InvokeRequest req, InvokeResult res) { System.out.println("\nLambda function returned:"); ByteBuffer response_payload = res.getPayload(); System.out.println(new String(response_payload.array())); System.exit(0); } public void onError(Exception e) { System.out.println(e.getMessage()); System.exit(1); } } public static void main(String[] args) { String function_name = "HelloFunction"; String function_input = "{\"who\":\"SDK for Java\"}"; AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient(); InvokeRequest req = new InvokeRequest() .withFunctionName(function_name) .withPayload(ByteBuffer.wrap(function_input.getBytes())); Future<InvokeResult> future_res = lambda.invokeAsync(req, new AsyncLambdaHandler()); System.out.print("Waiting for async callback"); while (!future_res.isDone() && !future_res.isCancelled()) { // perform some other tasks... try { Thread.sleep(1000); } catch (InterruptedException e) { System.err.println("Thread.sleep() was interrupted!"); System.exit(0); } System.out.print("."); } } }

最佳实操

回调执行

AsyncHandler 的实施在异步客户端拥有的线程池内执行。简短、快速执行的代码在您的 AsyncHandler 实施内最适合。如果您的处理程序方法包含长时间运行的代码或阻码,会导致对异步客户端所使用线程池的争用,并阻止客户端执行请求。如果需要从回调开始一种长期运行的任务,请在新的线程或应用程序托管的线程池中让回调运行其任务。

线程池配置

中的异步客户端 AWS SDK for Java 提供了一个适用于大多数应用程序的默认线程池。您可以实现自定义ExecutorService并将其传递给 AWS SDK for Java 异步客户端,以便更好地控制线程池的管理方式。

例如,您可以提供一个ExecutorService实现,该实现使用自定义ThreadFactory来控制池中线程的命名方式,或者记录有关线程使用情况的其他信息。

异步访问

SDK 中的TransferManager类为使用提供了异步支持 Amazon S3。 TransferManager管理异步上传和下载,提供详细的传输进度报告,并支持对不同事件的回调。