

 适用于 Java 的 AWS SDK 1.x于2025年 end-of-support 12月31日达到。我们建议您迁移到 [AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html) 以继续获得新功能、可用性改进和安全更新。

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

# 异步编程
<a name="basics-async"></a>

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

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

## Java Futures
<a name="basics-async-future"></a>

中的异步方法 适用于 Java 的 AWS SDK 返回一个 F [ut](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/Future.html) ure 对象，该对象包含*将来异步操作的*结果。

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

以下是一个异步操作的示例，该异步操作调用 Lambda 函数，接收`Future`可以容纳[InvokeResult](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/lambda/model/InvokeResult.html)对象的函数。`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);
    }
}
```

## 异步回调
<a name="basics-async-callback"></a>

除了使用 Java `Future` 对象监控异步请求的状态外，SDK 还允许您实现使用该[AsyncHandler](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/handlers/AsyncHandler.html)接口的类。 `AsyncHandler`提供了两种根据请求完成方式调用的方法：`onSuccess`和`onError`。

回调接口方法的主要优势是它让您无需轮询 `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(".");
        }
    }
}
```

## 最佳实践
<a name="basics-async-tips"></a>

### 回调执行
<a name="callback-execution"></a>

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

### 线程池配置
<a name="thread-pool-configuration"></a>

中的异步客户端 适用于 Java 的 AWS SDK 提供了一个适用于大多数应用程序的默认线程池。您可以实现自定义[ExecutorService](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ExecutorService.html)并将其传递给 适用于 Java 的 AWS SDK 异步客户端，以便更好地控制线程池的管理方式。

例如，您可以提供一个`ExecutorService`实现，该实现使用自定义[ThreadFactory](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ThreadFactory.html)来控制池中线程的命名方式，或者记录有关线程使用情况的其他信息。

### 异步访问
<a name="s3-asynchronous-access"></a>

SDK 中的[TransferManager](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/TransferManager.html)类为使用提供了异步支持 Amazon S3。 `TransferManager`管理异步上传和下载，提供详细的传输进度报告，并支持对不同事件的回调。