Как использовать ForkJoinPool в Spring Boot @Async?
Я хочу использовать ForkJoinPool в моем весеннем загрузочном проекте с аннотацией @Async, например ThreadPoolTaskExecutor
Например:-
@Bean("threadPoolTaskExecutor")
public TaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(1000);
executor.setThreadNamePrefix("Async-");
return executor;
}
Я использую https://dzone.com/articles/spring-boot-creating-asynchronous-methods-using-as эту ссылку в моем коде, но я хочу использовать ForkJoinPool вот так.
4 ответа
Это нормально использовать ForkJoinPool с асинхронным. Этот подход не совсем то, для чего был разработан ForkJoinPool, - который решает задачу "Разделяй и властвуй" и использует алгоритм перехвата работы, но для выполнения задач в стиле событий или блокирования ввода-вывода, и это допустимый вариант использования.
Итак, с базовым использованием вы можете сделать:
CompletableFuture.runAsync(() -> doSomething(), ForkJoinPool.commonPool());
Вы также можете создать пользовательский ForkJoinPool в асинхронном режиме. Рабочие в ForkJoinPool в асинхронном режиме обрабатывают задачи в порядке FIFO (первым пришел, первым вышел). По умолчанию ForkJoinPools обрабатывает такие задачи в порядке LIFO (последний пришел, первый вышел). Также настройка асинхронного режима касается только разветвленных задач, которые никогда не объединяются. Может использоваться для задач в стиле событий, которые отправляются, но никогда не присоединяются (задачи, которые выполняются для их побочных эффектов, а не для возврата результата, который будет обработан задачей разветвления и последующего присоединения).
Вы можете создать собственный ForkJoinPool с заданным параллелизмом в асинхронном режиме следующим образом (первый параметр - размер пула, последний - bool asyncMode):
ForkJoinPool pool = new ForkJoinPool(
6, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
Итак, что вы ищете:
@Bean("threadPoolTaskExecutor")
public Executor getAsyncExecutor() {
ForkJoinPool pool = new ForkJoinPool(
6, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
return pool;
}
На мой взгляд, вы не можете объединить @Async
аннотация с ForkJoinPool
учебный класс. ForkJoinPool
предназначен для разделения одной задачи на подзадачу для ее параллельного выполнения и объединения в результат. Параллельный поток использует ForkJoinPool
за кулисами. Чтобы выполнить задачу, используя ForkJoinPool
вам нужно реализовать RecursiveTask
или же RecursiveAction
интерфейс. Я никак не мог понять, как мы можем использовать эти вещи вместе.
Я не знаю, почему вы хотите это сделать, но все же вы можете использовать ForkJoinPool
за @Async
, Поскольку ForkJoinPool
реализует класс Executor
Но если мы посмотрим на документацию ForkJoinPool, я не вижу какого-либо метода для установки размера пула потоков, и вы рискуете его использовать.
конфиг
@Bean("threadPoolTaskExecutor")
public Executor getAsyncExecutor() {
ForkJoinPool pool = new ForkJoinPool();
return pool;
}
обслуживание
@Async("threadPoolTaskExecutor")
public void testRun() {
System.out.println(Thread.currentThread().getName());
}
Выход
ForkJoinPool-1-worker-1
И если вы очень заинтересованы в использовании ForkJoinPool
использование CompletableFuture.async
методы вместо весенней загрузки @Async
документы
Все асинхронные методы без явного аргумента Executor выполняются с использованием ForkJoinPool.commonPool() (если только он не поддерживает уровень параллелизма, равный по крайней мере двум, и в этом случае создается новый поток для выполнения каждой задачи)
Чтобы включить возможность выполнения асинхронного метода Spring, вы можете использовать @EnableAsync
аннотация в классе конфигурации.
@Configuration
@EnableAsync
public class ThreadConfig {
@Bean
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(4);
executor.setThreadNamePrefix("prate");
executor.initialize();
return executor;
}
}
В некоторых случаях вы не хотите, чтобы один и тот же пул потоков выполнял все задачи приложения. Вы могли бы хотеть отдельные пулы потоков с различными конфигурациями, поддерживающими наши функции. Таким образом, вы можете настроить конкретные ThreadPoolExecutor
лайк -
@Configuration
@EnableAsync
public class ThreadConfig {
@Bean(name = "specificTaskExecutor")
public TaskExecutor specificTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.initialize();
return executor;
}
}
Теперь функция должна установить значение квалификатора, чтобы определить целевого исполнителя конкретного исполнителя или TaskExecutor.
@Async("specificTaskExecutor")
public void runFromAnotherThreadPool() {
System.out.println("test here");
}