

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Ações em lote do Amazon SQS
<a name="sqs-batch-api-actions"></a>

O Amazon SQS fornece ações em lote para ajudar você a reduzir custos e manipular até dez mensagens com uma única ação. Essas ações em lote incluem:
+ `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`
+ `[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)`
+ `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`

Com as ações em lote, é possível realizar várias operações em uma única chamada de API, o que ajuda a otimizar o desempenho e reduzir custos. Você pode aproveitar a funcionalidade em lote usando a API de consulta ou qualquer AWS SDK que ofereça suporte às ações em lote do Amazon SQS.

**Detalhes importantes**
+ **Limite de tamanho de mensagem:** o tamanho total de todas as mensagens enviadas em uma única chamada de `SendMessageBatch` não pode exceder 1.048.576 bytes (1 MiB)
+ **Permissões:** não é possível definir permissões explicitamente para `SendMessageBatch`, `DeleteMessageBatch` ou `ChangeMessageVisibilityBatch`. Em vez disso, a definição de permissões para `SendMessage`, `DeleteMessage` ou `ChangeMessageVisibility` define permissões para as versões de lote correspondentes dessas ações.
+ **Suporte do console:** o console do Amazon SQS não é compatível com ações em lote. Você deve usar a API de consulta ou um AWS SDK para realizar operações em lote.

## Agrupar ações de mensagem em lotes
<a name="batching-message-actions"></a>

Para otimizar ainda mais os custos e a eficiência, considere as seguintes práticas recomendadas para agrupar ações de mensagens em lote:
+ **Ações de API em lote:** use as [ações de API em lote do Amazon SQS](#sqs-batch-api-actions) para enviar, receber e excluir mensagens, e para alterar o tempo limite de visibilidade de várias mensagens com uma única ação. Isso reduz o número de chamadas de API e os custos associados.
+ **Buffer do lado do cliente e sondagem longa:** combine o buffer do lado do cliente com o agrupamento de solicitações em lote usando a sondagem longa com o [cliente assíncrono em buffer](sqs-client-side-buffering-request-batching.md) incluído no AWS SDK para Java. Essa abordagem ajuda a minimizar o número de solicitações e otimiza o gerenciamento de grandes volumes de mensagens.

**nota**  
Atualmente, o cliente assíncrono no buffer do Amazon SQS não oferece suporte a filas FIFO.

# Habilitar o buffer no lado do cliente e o agrupamento de solicitações em lote com o Amazon SQS
<a name="sqs-client-side-buffering-request-batching"></a>

O [AWS SDK para Java](https://aws.amazon.com/sdkforjava/) inclui o `AmazonSQSBufferedAsyncClient`, que acessa o Amazon SQS. Esse cliente permite um simples agrupamento em lote de solicitações usando o buffer do lado do cliente. Chamadas feitas do cliente são armazenadas primeiramente em buffer, depois enviadas como uma solicitação em lote para o Amazon SQS.

O armazenamento em buffer no lado do cliente permite que até 10 solicitações sejam armazenadas em buffer e enviadas como uma solicitação em lote, diminuindo o custo de uso do Amazon SQS e reduzindo o número de solicitações enviadas. O `AmazonSQSBufferedAsyncClient` armazena tanto as chamadas síncronas quanto as assíncronas em buffer. Solicitações em lote e suporte para [sondagem longa](sqs-short-and-long-polling.md) também podem ajudar a aumentar a taxa de transferência. Para obter mais informações, consulte [Aumento do throughput usando escalabilidade horizontal e processamento de ações em lote com o Amazon SQS](sqs-throughput-horizontal-scaling-and-batching.md).

como o `AmazonSQSBufferedAsyncClient` implementa a mesma interface que o `AmazonSQSAsyncClient`, migrar de `AmazonSQSAsyncClient` para `AmazonSQSBufferedAsyncClient` normalmente requer apenas pequenas mudanças no seu código existente.

**nota**  
Atualmente, o cliente assíncrono no buffer do Amazon SQS não oferece suporte a filas FIFO.

## Usando a Amazon SQSBuffered AsyncClient
<a name="using-buffered-async-client"></a>

Antes de começar, conclua as etapas em [Configurar o Amazon SQS](sqs-setting-up.md). 

### AWS SDK para Java 1.x
<a name="using-buffered-async-client-java1"></a>

Para o AWS SDK for Java 1.x, você pode criar um `AmazonSQSBufferedAsyncClient` novo com base no exemplo a seguir:

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync);
```

Depois de criar o novo `AmazonSQSBufferedAsyncClient`, você pode usá-lo para enviar várias solicitações ao Amazon SQS (da mesma forma que faria com o `AmazonSQSAsyncClient`), por exemplo:

```
final CreateQueueRequest createRequest = new CreateQueueRequest().withQueueName("MyQueue");
 
final CreateQueueResult res = bufferedSqs.createQueue(createRequest);
 
final SendMessageRequest request = new SendMessageRequest();
final String body = "Your message text" + System.currentTimeMillis();
request.setMessageBody( body );
request.setQueueUrl(res.getQueueUrl());
 
final Future<SendMessageResult> sendResult = bufferedSqs.sendMessageAsync(request);
 
final ReceiveMessageRequest receiveRq = new ReceiveMessageRequest()
    .withMaxNumberOfMessages(1)
    .withQueueUrl(queueUrl);
final ReceiveMessageResult rx = bufferedSqs.receiveMessage(receiveRq);
```

### Configurando a Amazon SQSBuffered AsyncClient
<a name="configuring-buffered-async-client"></a>

O `AmazonSQSBufferedAsyncClient` é pré-configurado com configurações que funcionarão para a maioria dos casos de uso. Você pode configurar ainda mais o `AmazonSQSBufferedAsyncClient`, por exemplo:

1. Crie uma instância da classe `QueueBufferConfig` com os parâmetros de configuração necessários.

1. Informe a instância para o construtor `AmazonSQSBufferedAsyncClient`.

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
final QueueBufferConfig config = new QueueBufferConfig()
    .withMaxInflightReceiveBatches(5)
    .withMaxDoneReceiveBatches(15);
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync, config);
```


**QueueBufferConfig parâmetros de configuração**  

| Parâmetro | Valor padrão  | Description | 
| --- | --- | --- | 
| longPoll | true |  Quando `longPoll` está definido como `true`, `AmazonSQSBufferedAsyncClient` tenta usar a sondagem longa ao consumir mensagens.  | 
| longPollWaitTimeoutSeconds | 20 s |  A quantidade máxima de tempo, em segundos, em que uma chamada `ReceiveMessage` é bloqueada no servidor aguardando as mensagens aparecerem na fila antes de retornar com um resultado de recebimento vazio.  Quando a sondagem longa está desativada, essa configuração não tem efeito.   | 
| maxBatchOpenMs | 200ms |  A quantidade máxima de tempo (em milissegundos) que uma chamada de saída aguarda outras chamadas com as quais ela coloca mensagens do mesmo tipo em lote. Quanto maior for a configuração, menos lotes serão necessários para executar a mesma quantidade de trabalho (no entanto, a primeira chamada em um lote deve passar mais tempo em espera). Quando esse parâmetro é definido como `0`, as solicitações enviadas não aguardam outras solicitações, desativando efetivamente o processamento em lotes.  | 
| maxBatchSize | 10 solicitações por lote |  O número máximo de mensagens que são armazenadas em lote em uma única solicitação. Quanto maior a configuração, menos lotes serão necessários para executar o mesmo número de solicitações.  Dez solicitações por lote é o valor máximo permitido para o Amazon SQS.   | 
| maxBatchSizeBytes | 1 MiB |  O tamanho máximo de um lote de mensagens, em bytes, que o cliente tenta enviar ao Amazon SQS.  1 MiB é o valor máximo permitido para o Amazon SQS.   | 
| maxDoneReceiveBatches | 10 lotes |  O número máximo de lotes de recebimento que `AmazonSQSBufferedAsyncClient` pré-busca e armazena no lado do cliente. Quanto maior for a configuração, mais solicitações de recebimento poderão ser atendidas sem a necessidade de fazer uma chamada ao Amazon SQS (no entanto, quanto mais mensagens forem buscadas previamente, mais tempo elas permanecerão no buffer, fazendo com que o tempo limite de visibilidade expire).  `0` indica que toda a pré-busca de mensagens está desabilitada e as mensagens são consumidas apenas sob demanda.   | 
| maxInflightOutboundBatches | 5 lotes |  O número máximo de lotes de saída ativos que podem ser processados ao mesmo tempo. Quanto maior for a configuração, mais rapidamente os lotes de saída poderão ser enviados (sujeito a outras cotas, como CPU ou largura de banda) e mais threads serão consumidos pelo `AmazonSQSBufferedAsyncClient`.  | 
| maxInflightReceiveBatches | 10 lotes |  O número máximo de lotes de recebimento ativos que podem ser processados ao mesmo tempo. Quanto maior for a configuração, mais mensagens serão recebidas (sujeito a outras cotas, como CPU ou largura de banda) e mais threads serão consumidos pelo `AmazonSQSBufferedAsyncClient`.  `0` indica que toda a pré-busca de mensagens está desabilitada e as mensagens são consumidas apenas sob demanda.   | 
| visibilityTimeoutSeconds | -1 |  Quando esse parâmetro é definido como um valor positivo e diferente de zero, o tempo limite de visibilidade definido aqui substitui o tempo limite de visibilidade definido na fila a partir da qual as mensagens são consumidas.  `-1` indica que a configuração padrão foi selecionada para a fila. Não é possível configurar o tempo limite de visibilidade para `0`.   | 

### AWS SDK para Java 2.x
<a name="using-buffered-async-client-java2"></a>

Para o AWS SDK for Java 2.x, você pode criar um `SqsAsyncBatchManager` novo com base no exemplo a seguir:

```
// Create the basic Sqs Async Client
SqsAsyncClient sqs = SqsAsyncClient.builder() 
    .region(Region.US_EAST_1) 
    .build();

// Create the batch manager
SqsAsyncBatchManager sqsAsyncBatchManager = sqs.batchManager();
```

Depois de criar o novo `SqsAsyncBatchManager`, você pode usá-lo para enviar várias solicitações ao Amazon SQS (da mesma forma que faria com o `SqsAsyncClient`), por exemplo:

```
final String queueName = "MyAsyncBufferedQueue" + UUID.randomUUID();
final CreateQueueRequest request = CreateQueueRequest.builder().queueName(queueName).build();
final String queueUrl = sqs.createQueue(request).join().queueUrl();
System.out.println("Queue created: " + queueUrl);


// Send messages
CompletableFuture<SendMessageResponse> sendMessageFuture;
for (int i = 0; i < 10; i++) {
    final int index = i;
    sendMessageFuture = sqsAsyncBatchManager.sendMessage(
            r -> r.messageBody("Message " + index).queueUrl(queueUrl));
    SendMessageResponse response= sendMessageFuture.join();
    System.out.println("Message " + response.messageId() + " sent!");
}

// Receive messages with customized configurations
CompletableFuture<ReceiveMessageResponse> receiveResponseFuture = customizedBatchManager.receiveMessage(
        r -> r.queueUrl(queueUrl)
                .waitTimeSeconds(10)
                .visibilityTimeout(20)
                .maxNumberOfMessages(10)
);
System.out.println("You have received " + receiveResponseFuture.join().messages().size() + " messages in total.");

// Delete messages
DeleteQueueRequest deleteQueueRequest =  DeleteQueueRequest.builder().queueUrl(queueUrl).build();
int code = sqs.deleteQueue(deleteQueueRequest).join().sdkHttpResponse().statusCode();
System.out.println("Queue is deleted, with statusCode " + code);
```

### Configurando SqsAsyncBatchManager
<a name="configuring-SqsAsyncBatchManager"></a>

O `SqsAsyncBatchManager` é pré-configurado com configurações que funcionarão para a maioria dos casos de uso. Você pode configurar ainda mais o `SqsAsyncBatchManager`, por exemplo:

Como criar configurações personalizadas usando o `SqsAsyncBatchManager.Builder`:

```
SqsAsyncBatchManager customizedBatchManager = SqsAsyncBatchManager.builder() 
    .client(sqs)
    .scheduledExecutor(Executors.newScheduledThreadPool(5))
    .overrideConfiguration(b -> b 
        .maxBatchSize(10)
        .sendRequestFrequency(Duration.ofMillis(200))
        .receiveMessageMinWaitDuration(Duration.ofSeconds(10))
        .receiveMessageVisibilityTimeout(Duration.ofSeconds(20)) 
        .receiveMessageAttributeNames(Collections.singletonList("*"))
        .receiveMessageSystemAttributeNames(Collections.singletonList(MessageSystemAttributeName.ALL)))
    .build();
```


**Parâmetros do `BatchOverrideConfiguration`**  

| Parâmetro | Valor padrão  | Description | 
| --- | --- | --- | 
| maxBatchSize |  10 solicitações por lote  | O número máximo de mensagens que são armazenadas em lote em uma única solicitação. Quanto maior a configuração, menos lotes serão necessários para executar o mesmo número de solicitações.  O valor máximo permitido para o Amazon SQS é de 10 solicitações por lote.  | 
| sendRequestFrequency |  200ms  | A quantidade máxima de tempo (em milissegundos) que uma chamada de saída aguarda outras chamadas com as quais ela coloca mensagens do mesmo tipo em lote. Quanto maior for a configuração, menos lotes serão necessários para executar a mesma quantidade de trabalho (no entanto, a primeira chamada em um lote deve passar mais tempo em espera). Quando esse parâmetro é definido como `0`, as solicitações enviadas não aguardam outras solicitações, desativando efetivamente o processamento em lotes. | 
| receiveMessageVisibilityTimeout |  -1  | Quando esse parâmetro é definido como um valor positivo e diferente de zero, o tempo limite de visibilidade definido aqui substitui o tempo limite de visibilidade definido na fila a partir da qual as mensagens são consumidas.   `1` indica que a configuração padrão foi selecionada para a fila. Não é possível configurar o tempo limite de visibilidade para `0`.   | 
| receiveMessageMinWaitDuration |  50 ms  | O tempo mínimo (em milissegundos) que uma chamada de `receiveMessage` aguardará para que as mensagens disponíveis sejam buscadas. Quanto maior a configuração, menos lotes serão necessários para executar o mesmo número de solicitações.  | 

# Aumento do throughput usando escalabilidade horizontal e processamento de ações em lote com o Amazon SQS
<a name="sqs-throughput-horizontal-scaling-and-batching"></a>

O Amazon SQS é compatível com mensagens de alto throughput. Para obter detalhes sobre os limites de throughput, consulte [Cotas de mensagens do Amazon SQS](quotas-messages.md).

Para maximizar o throughput:
+ [Escale](#horizontal-scaling) produtores e consumidores horizontalmente adicionando mais instâncias de cada um.
+ Use o [agrupamento de ações em lote](#request-batching) para enviar ou receber várias mensagens em uma única solicitação, reduzindo a sobrecarga de chamadas da API.

## Escalabilidade horizontal
<a name="horizontal-scaling"></a>

Como você acessa o Amazon SQS por meio de um protocolo HTTP de solicitação-resposta, *a latência da solicitação* (o intervalo de tempo entre o início de uma solicitação e o recebimento de uma resposta) limita a taxa de transferência que você pode obter de uma única thread por meio de uma única conexão. Por exemplo, se a latência média de um cliente com base no Amazon EC2 para o Amazon SQS na mesma região for de cerca de 20 ms, a taxa de transferência máxima de uma única thread por meio de uma única conexão será em média 50 TPS. 

*A escalabilidade horizontal* envolve o aumento do número de produtores de mensagem (que fazem a solicitação `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)`) e dos consumidores (que fazem solicitações `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` e `[DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)`) para aumentar sua taxa de transferência de fila geral. Você pode escalar horizontalmente de três formas:
+ Aumentar o número de threads por cliente
+ Adicionar mais clientes
+ Aumentar o número de threads por cliente e adicionar mais clientes

Ao adicionar mais clientes, você obtém ganhos essencialmente lineares na taxa de transferência da fila. Por exemplo, se você dobrar o número de clientes, terá duas vezes a taxa de transferência. 

## Processamento de ações em lotes
<a name="request-batching"></a>

*O processamento em lotes* executa mais trabalho durante a ida e a volta do serviço (por exemplo, quando você envia várias mensagens com uma única solicitação `SendMessageBatch`). As ações de em lote do Amazon SQS são `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`, `[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)` e `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`. Para aproveitar o processamento em lotes sem alterar os produtores ou consumidores, você pode usar o [cliente assíncrono armazenado em buffer para o Amazon SQS](sqs-client-side-buffering-request-batching.md).

**nota**  
Como `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` pode processar 10 mensagens por vez, não há nenhuma ação `ReceiveMessageBatch`.

O processamento em lotes distribui a latência da ação de lote nas várias mensagens de uma solicitação em lote em vez de aceitar toda a latência para uma única mensagem (por exemplo, uma solicitação `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)`). Como cada ida e volta carrega mais trabalho, as solicitações de lote tornam mais eficiente o uso de threads e conexões, melhorando, dessa forma, a taxa de transferência.

Você pode combinar processamentos em lote com escalabilidade horizontal para fornecer taxa de transferência com menos threads, conexões e solicitações em comparação com as solicitações de mensagens individuais. Você pode usar ações em lotes do Amazon SQS para enviar, receber ou excluir até 10 mensagens por vez. Como o Amazon SQS cobra por solicitação, o processamento em lotes pode reduzir substancialmente os custos. 

O processamento em lotes pode criar certa complexidade para o seu aplicativo (por exemplo, o aplicativo precisa acumular as mensagens antes de enviá-las e, às vezes, precisará esperar mais por uma resposta). No entanto, o processamento em lotes pode ser eficaz nos seguintes casos: 
+ Seu aplicativo gera muitas mensagens em um curto intervalo de tempo, portanto, o atraso nunca é muito longo. 
+ Um consumidor de mensagem busca as mensagens de uma fila a seu critério, ao contrário de produtores de mensagem típicos que precisam enviar mensagens em resposta a eventos que eles não controlam. 

**Importante**  
Uma solicitação de lote pode ser bem-sucedida, mesmo que ocorra falha nas mensagens individuais no lote. Após uma solicitação de lote, você sempre deve verificar a existência de falhas em mensagens individuais e repetir a ação, se necessário.

## Exemplo de Java funcional para operações únicas e solicitações em lote
<a name="working-java-example-batch-requests"></a>

### Pré-requisitos
<a name="batch-request-java-example-prerequisites"></a>

Adicione os pacotes `aws-java-sdk-sqs.jar`, `aws-java-sdk-ec2.jar` e `commons-logging.jar` ao caminho da classe de compilação do Java. O exemplo a seguir mostra essas dependências em um arquivo `pom.xml` do projeto Maven.

```
<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-sqs</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-ec2</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>LATEST</version>
    </dependency>
</dependencies>
```

### SimpleProducerConsumer.java
<a name="batch-request-java-example-code"></a>

O exemplo de código Java a seguir implementa um padrão simples de produtor-consumidor. O thread principal gera um número de threads de produtor e consumidor que processam mensagens de 1 KB em um determinado momento. Ele inclui produtores e os consumidores que fazem solicitações de operação únicas e outros que fazem solicitações de lote.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Start a specified number of producer and consumer threads, and produce-consume
 * for the least of the specified duration and 1 hour. Some messages can be left
 * in the queue because producers and consumers might not be in exact balance.
 */
public class SimpleProducerConsumer {

    // The maximum runtime of the program.
    private final static int MAX_RUNTIME_MINUTES = 60;
    private final static Log log = LogFactory.getLog(SimpleProducerConsumer.class);

    public static void main(String[] args) throws InterruptedException {

        final Scanner input = new Scanner(System.in);

        System.out.print("Enter the queue name: ");
        final String queueName = input.nextLine();

        System.out.print("Enter the number of producers: ");
        final int producerCount = input.nextInt();

        System.out.print("Enter the number of consumers: ");
        final int consumerCount = input.nextInt();

        System.out.print("Enter the number of messages per batch: ");
        final int batchSize = input.nextInt();

        System.out.print("Enter the message size in bytes: ");
        final int messageSizeByte = input.nextInt();

        System.out.print("Enter the run time in minutes: ");
        final int runTimeMinutes = input.nextInt();

        /*
         * Create a new instance of the builder with all defaults (credentials
         * and region) set automatically. For more information, see Creating
         * Service Clients in the AWS SDK for Java Developer Guide.
         */
        final ClientConfiguration clientConfiguration = new ClientConfiguration()
                .withMaxConnections(producerCount + consumerCount);

        final AmazonSQS sqsClient = AmazonSQSClientBuilder.standard()
                .withClientConfiguration(clientConfiguration)
                .build();

        final String queueUrl = sqsClient
                .getQueueUrl(new GetQueueUrlRequest(queueName)).getQueueUrl();

        // The flag used to stop producer, consumer, and monitor threads.
        final AtomicBoolean stop = new AtomicBoolean(false);

        // Start the producers.
        final AtomicInteger producedCount = new AtomicInteger();
        final Thread[] producers = new Thread[producerCount];
        for (int i = 0; i < producerCount; i++) {
            if (batchSize == 1) {
                producers[i] = new Producer(sqsClient, queueUrl, messageSizeByte,
                        producedCount, stop);
            } else {
                producers[i] = new BatchProducer(sqsClient, queueUrl, batchSize,
                        messageSizeByte, producedCount,
                        stop);
            }
            producers[i].start();
        }

        // Start the consumers.
        final AtomicInteger consumedCount = new AtomicInteger();
        final Thread[] consumers = new Thread[consumerCount];
        for (int i = 0; i < consumerCount; i++) {
            if (batchSize == 1) {
                consumers[i] = new Consumer(sqsClient, queueUrl, consumedCount,
                        stop);
            } else {
                consumers[i] = new BatchConsumer(sqsClient, queueUrl, batchSize,
                        consumedCount, stop);
            }
            consumers[i].start();
        }

        // Start the monitor thread.
        final Thread monitor = new Monitor(producedCount, consumedCount, stop);
        monitor.start();

        // Wait for the specified amount of time then stop.
        Thread.sleep(TimeUnit.MINUTES.toMillis(Math.min(runTimeMinutes,
                MAX_RUNTIME_MINUTES)));
        stop.set(true);

        // Join all threads.
        for (int i = 0; i < producerCount; i++) {
            producers[i].join();
        }

        for (int i = 0; i < consumerCount; i++) {
            consumers[i].join();
        }

        monitor.interrupt();
        monitor.join();
    }

    private static String makeRandomString(int sizeByte) {
        final byte[] bs = new byte[(int) Math.ceil(sizeByte * 5 / 8)];
        new Random().nextBytes(bs);
        bs[0] = (byte) ((bs[0] | 64) & 127);
        return new BigInteger(bs).toString(32);
    }

    /**
     * The producer thread uses {@code SendMessage}
     * to send messages until it is stopped.
     */
    private static class Producer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        Producer(AmazonSQS sqsQueueBuffer, String queueUrl, int messageSizeByte,
                 AtomicInteger producedCount, AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        /*
         * The producedCount object tracks the number of messages produced by
         * all producer threads. If there is an error, the program exits the
         * run() method.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    sqsClient.sendMessage(new SendMessageRequest(queueUrl,
                            theMessage));
                    producedCount.incrementAndGet();
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Producer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The producer thread uses {@code SendMessageBatch}
     * to send messages until it is stopped.
     */
    private static class BatchProducer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        BatchProducer(AmazonSQS sqsQueueBuffer, String queueUrl, int batchSize,
                      int messageSizeByte, AtomicInteger producedCount,
                      AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final SendMessageBatchRequest batchRequest =
                            new SendMessageBatchRequest().withQueueUrl(queueUrl);

                    final List<SendMessageBatchRequestEntry> entries =
                            new ArrayList<SendMessageBatchRequestEntry>();
                    for (int i = 0; i < batchSize; i++)
                        entries.add(new SendMessageBatchRequestEntry()
                                .withId(Integer.toString(i))
                                .withMessageBody(theMessage));
                    batchRequest.setEntries(entries);

                    final SendMessageBatchResult batchResult =
                            sqsClient.sendMessageBatch(batchRequest);
                    producedCount.addAndGet(batchResult.getSuccessful().size());

                    /*
                     * Because SendMessageBatch can return successfully, but
                     * individual batch items fail, retry the failed batch items.
                     */
                    if (!batchResult.getFailed().isEmpty()) {
                        log.warn("Producer: retrying sending "
                                + batchResult.getFailed().size() + " messages");
                        for (int i = 0, n = batchResult.getFailed().size();
                             i < n; i++) {
                            sqsClient.sendMessage(new
                                    SendMessageRequest(queueUrl, theMessage));
                            producedCount.incrementAndGet();
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchProducer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code DeleteMessage}
     * to consume messages until it is stopped.
     */
    private static class Consumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        Consumer(AmazonSQS sqsClient, String queueUrl, AtomicInteger consumedCount,
                 AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        /*
         * Each consumer thread receives and deletes messages until the main
         * thread stops the consumer thread. The consumedCount object tracks the
         * number of messages that are consumed by all consumer threads, and the
         * count is logged periodically.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    try {
                        final ReceiveMessageResult result = sqsClient
                                .receiveMessage(new
                                        ReceiveMessageRequest(queueUrl));

                        if (!result.getMessages().isEmpty()) {
                            final Message m = result.getMessages().get(0);
                            sqsClient.deleteMessage(new
                                    DeleteMessageRequest(queueUrl,
                                    m.getReceiptHandle()));
                            consumedCount.incrementAndGet();
                        }
                    } catch (AmazonClientException e) {
                        log.error(e.getMessage());
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Consumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code
     * DeleteMessageBatch} to consume messages until it is stopped.
     */
    private static class BatchConsumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        BatchConsumer(AmazonSQS sqsClient, String queueUrl, int batchSize,
                      AtomicInteger consumedCount, AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final ReceiveMessageResult result = sqsClient
                            .receiveMessage(new ReceiveMessageRequest(queueUrl)
                                    .withMaxNumberOfMessages(batchSize));

                    if (!result.getMessages().isEmpty()) {
                        final List<Message> messages = result.getMessages();
                        final DeleteMessageBatchRequest batchRequest =
                                new DeleteMessageBatchRequest()
                                        .withQueueUrl(queueUrl);

                        final List<DeleteMessageBatchRequestEntry> entries =
                                new ArrayList<DeleteMessageBatchRequestEntry>();
                        for (int i = 0, n = messages.size(); i < n; i++)
                            entries.add(new DeleteMessageBatchRequestEntry()
                                    .withId(Integer.toString(i))
                                    .withReceiptHandle(messages.get(i)
                                            .getReceiptHandle()));
                        batchRequest.setEntries(entries);

                        final DeleteMessageBatchResult batchResult = sqsClient
                                .deleteMessageBatch(batchRequest);
                        consumedCount.addAndGet(batchResult.getSuccessful().size());

                        /*
                         * Because DeleteMessageBatch can return successfully,
                         * but individual batch items fail, retry the failed
                         * batch items.
                         */
                        if (!batchResult.getFailed().isEmpty()) {
                            final int n = batchResult.getFailed().size();
                            log.warn("Producer: retrying deleting " + n
                                    + " messages");
                            for (BatchResultErrorEntry e : batchResult
                                    .getFailed()) {

                                sqsClient.deleteMessage(
                                        new DeleteMessageRequest(queueUrl,
                                                messages.get(Integer
                                                        .parseInt(e.getId()))
                                                        .getReceiptHandle()));

                                consumedCount.incrementAndGet();
                            }
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchConsumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * This thread prints every second the number of messages produced and
     * consumed so far.
     */
    private static class Monitor extends Thread {
        private final AtomicInteger producedCount;
        private final AtomicInteger consumedCount;
        private final AtomicBoolean stop;

        Monitor(AtomicInteger producedCount, AtomicInteger consumedCount,
                AtomicBoolean stop) {
            this.producedCount = producedCount;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    Thread.sleep(1000);
                    log.info("produced messages = " + producedCount.get()
                            + ", consumed messages = " + consumedCount.get());
                }
            } catch (InterruptedException e) {
                // Allow the thread to exit.
            }
        }
    }
}
```

### Monitorar métricas de volume da execução de exemplo
<a name="batch-request-java-example-monitoring-metrics"></a>

O Amazon SQS gera automaticamente métricas de volume para mensagens enviadas, recebidas e excluídas. Você pode acessar essas métricas e outras por meio da guia **Monitoring (Monitoramento)** de sua fila ou no [console do CloudWatch ](https://console.aws.amazon.com/cloudwatch/home).

**nota**  
As métricas podem levar até 15 minutos após a fila começar para ficar disponíveis.