Passando parâmetros para encadeamentos Java

Passando parâmetros para encadeamentos Java

 1. Visão geral

Neste tutorial, percorreremos diferentes opções disponíveis para passar parâmetros para um Javathread.

2. Princípios básicos do tópico

Como um lembrete rápido, podemos criar um encadeamento in Java porhttps://www.example.com/java-runnable-vs-extending-thread orCallable.

Para executar um thread, podemos invocarThread#start (passando uma instância deRunnable) ouuse a thread pool enviando-o para umExecutorService.

Nenhuma dessas abordagens aceita parâmetros extras, no entanto.

Vamos ver o que podemos fazer para passar parâmetros para um thread.

3. Envio de parâmetros no construtor

A primeira maneira de enviar um parâmetro a um thread é simplesmente fornecê-lo ao nossoRunnable orCallable em seu construtor.

Vamos criar umAverageCalculator que aceita uma matriz de números e retorna sua média:

public class AverageCalculator implements Callable {

    int[] numbers;

    public AverageCalculator(int... numbers) {
        this.numbers = numbers == null ? new int[0] : numbers;
    }

    @Override
    public Double call() throws Exception {
        return IntStream.of(numbers).average().orElse(0d);
    }
}

A seguir, forneceremos alguns números para o nosso thread da calculadora média e validaremos o resultado:

@Test
public void whenSendingParameterToCallable_thenSuccessful() throws Exception {
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Future result = executorService.submit(new AverageCalculator(1, 2, 3));
    try {
        assertEquals(2.0, result.get().doubleValue());
    } finally {
        executorService.shutdown();
    }
}

Observe que isso funciona porquewe’ve handed our class its state before launching the thread.

4. Envio de parâmetros por meio de um fechamento

Outra maneira de passar parâmetros para um thread é criando um fechamento.

Umclosure é um escopo que pode herdar parte do escopo de seu pai -we see it with lambdas and anonymous inner classes.

Vamos estender nosso exemplo anterior e criar dois threads.

O primeiro calculará a média:

executorService.submit(() -> IntStream.of(numbers).average().orElse(0d));

E, o segundo fará a soma:

executorService.submit(() -> IntStream.of(numbers).sum());

Vamos ver como podemos passar o mesmo parâmetro para ambos os threads e obter o resultado:

@Test
public void whenParametersToThreadWithLamda_thenParametersPassedCorrectly()
  throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    int[] numbers = new int[] { 4, 5, 6 };

    try {
        Future sumResult =
          executorService.submit(() -> IntStream.of(numbers).sum());
        Future averageResult =
          executorService.submit(() -> IntStream.of(numbers).average().orElse(0d));
        assertEquals(Integer.valueOf(15), sumResult.get());
        assertEquals(Double.valueOf(5.0), averageResult.get());
    } finally {
        executorService.shutdown();
    }
}

Uma coisa importante a lembrar ékeep the parameters effectively final ou não seremos capazes de entregá-los ao fechamento.

Also, the same concurrency rules apply here as everywhere. Se alterarmos um valor no arraynumbers enquanto os threads estão em execução, não há garantia de que eles o verão semintroducingsome synchronization.

E para finalizar aqui, uma classe interna anônima também teria funcionado, digamos, se estamos usando uma versão mais antiga do Java:

final int[] numbers = { 1, 2, 3 };
Thread parameterizedThread = new Thread(new Callable() {
    @Override
    public Double call() {
        return calculateTheAverage(numbers);
    }
});
parameterizedThread.start();

5. Conclusão

Neste artigo, descobrimos as diferentes opções disponíveis para passar parâmetros para um encadeamento Java.

Como sempre, as amostras de código estão disponíveisover on Github.