Как использовать 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");
}
Другие вопросы по тегам