#java #spring #multithreading #spring-boot #parallel-processing
#java #spring #многопоточность #весенняя загрузка #параллельная обработка
Вопрос:
У меня есть приведенный ниже код. Я хочу выполнять m3()
параллельно 3 потоками, поскольку я выполняю m1 и m2.
Как я могу этого добиться. Я использую Spring Boot и java 8. Возможно ли выполнить m3()
с помощью службы исполнителя.
@Service
class Main {
@Autowired
Private Other other;
ExecutorService executorService = Executors.newFixedThreadPool(3);
void test_method() {
for (int i = 0; i < 201; i ) {
executorService.submit(() -> other.m1()); // works fine as expected
executorService.submit(() -> other.m2()); // works fine as expected
executorService.submit(() -> other.m3(i)); // compilation error as expected
}
}
Ошибка
Локальная переменная, определенная i во включающей области, должна быть окончательной или фактически окончательной
Методы приведены ниже
@Service
class Other {
void m1() {
}
String m2() {
return "Hello";
}
int m3(int n) {
return n;
}
}
Комментарии:
1. В чем ошибка?
2.
Local variable i defined in an enclosing scope must be final or effectively final
Ответ №1:
В Java вы не можете использовать неокончательные переменные в анонимных внутренних классах, то есть лямбда-выражения.
- Конечная переменная — это та, которая создается только один раз.
- Эффективно-конечная переменная — это та, значение которой никогда не изменяется после инициализации.
Одним из возможных обходных путей является использование IntStream.range
IntStream.forEach
методов и:
IntStream.range(0, 201).forEach(i -> {
executorService.submit(() -> other.m1());
executorService.submit(() -> other.m2());
executorService.submit(() -> other.m3(i));
});
Комментарии:
1. Спасибо. Но ваш метод будет работать для int. Предположим, я передавал какой-то пользовательский Pojo, такой как MyObject, в m3(), тогда как бы я это сделал? Есть какой-нибудь элегантный способ сделать это?
2. Зачарованный цикл работает:
for (Pojo pojo: list) { executorService.submit(() -> other.m3(pojo)); }
Ответ №2:
попробуйте это:
void test_method() {
for (int i = 0; i < 201; i ) {
executorService.submit(other::m1);
executorService.submit(other::m2);
final int i1 = i;
executorService.submit(() -> other.m3(i1));
}
}
Комментарии:
1. я постараюсь, спасибо. И я решил проблему , используя создание контейнерного класса для int
final MyContainer myContainer = new MyContainer(i); myContainer.getIntValue()
. Но есть ли у вас какое-нибудь элегантное решение для выполнения m3() параллельно с ot без ExecutorService2. и ваше и мое решение почти одинаковы. Но предположим, что я передавал какой-то пользовательский класс Pojo в m3
3. @PaleBlueDot выполнить m3() параллельно с чем? он уже выполнен с максимально возможным логическим параллелизмом. Для достижения максимального физического параллелизма используйте ExecutorService ExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().Available Processors());