Передача параметров java-потокам
1. Обзор
В этом учебнике мы пройдемся по различным опциям, доступным для передачи параметров в поток Java.
2. Основы резьбы
В качестве краткого напоминания мы можем создать поток на Java по реализация Runnable или Вызов .
Чтобы запустить поток, мы можем вызвать Нить для начала (проходя экземпляр Бег ) или использовать пул потоков представив его на ИсполнительСервис .
Однако ни один из этих подходов не принимает никаких дополнительных параметров.
Давайте посмотрим, что мы можем сделать, чтобы передать параметры в поток.
3. Параметры отправки в конструкторе
Первый способ отправить параметр в поток просто предоставить его нашим Бег или Вызов в их конструктора.
Давайте создадим СреднийCalculator который принимает массив чисел и возвращает их в среднем:
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); } }
Далее мы предоставим некоторые цифры для нашего среднего потока калькулятора и проверяем выход:
@Test public void whenSendingParameterToCallable_thenSuccessful() throws Exception { ExecutorService executorService = Executors.newSingleThreadExecutor(); Futureresult = executorService.submit(new AverageCalculator(1, 2, 3)); try { assertEquals(2.0, result.get().doubleValue()); } finally { executorService.shutdown(); } }
Обратите внимание, что причина этого работает в том, что мы передали нашему классу его состояние перед запуском потока.
4. Отправка параметров через закрытие
Другим способом передачи параметров в поток является создание системы .
закрытие является областью, которая может унаследовать некоторые области его родителей – мы видим это с лямбдами и анонимными внутренними классами.
Давайте расширим наш предыдущий пример и создадим два потока.
Первый вычислит среднее значение:
executorService.submit(() -> IntStream.of(numbers).average().orElse(0d));
И, второй сделает сумму:
executorService.submit(() -> IntStream.of(numbers).sum());
Давайте посмотрим, как мы можем передать один и тот же параметр обоим потокам и получить результат:
@Test public void whenParametersToThreadWithLamda_thenParametersPassedCorrectly() throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(2); int[] numbers = new int[] { 4, 5, 6 }; try { FuturesumResult = 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(); } }
Одна важная вещь, чтобы помнить, чтобы сохранить параметры эффективно окончательным или мы не сможем передать их закрытия.
Кроме того, здесь действуют те же правила конваляции, что и везде. Если мы изменим значение в цифры массив в то время как потоки работают, нет никакой гарантии, что они будут видеть его без введение некоторые синхронизированные .
И, чтобы завершить здесь, анонимный внутренний класс тоже работал бы, скажем, если бы мы использовали старую версию Java:
final int[] numbers = { 1, 2, 3 }; Thread parameterizedThread = new Thread(new Callable() { @Override public Double call() { return calculateTheAverage(numbers); } }); parameterizedThread.start();
5. Заключение
В этой статье мы обнаружили различные варианты передачи параметров в поток Java.
Как всегда, образцы кода доступны более на Github .