简体   繁体   English

如何在 Java 中运行同一进程的多个线程 - Spring Boot

[英]How to run multiple threads of the same process in Java - Spring Boot

I have a scheduled task which needs to launch multiple threads of the same process when executed, is it possible to set a specific number of threads to be launched when the process is kicked off?我有一个计划任务,它需要在执行时启动同一进程的多个线程,是否可以设置在进程启动时启动的特定线程数?

In the application class I have the following TaskExecutor beans configured在应用程序类中,我配置了以下TaskExecutor bean

    @Bean("threadFooExecutor")
    public TaskExecutor getFooExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("Foo-");
        return executor;
    }```

    @Bean("threadBarExecutor")
    public TaskExecutor getBarExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("Bar-");
        return executor;
    }

Async processes configured in process class进程类中配置的异步进程

    @Async("threadFooExecutor")
    @Scheduled(fixedRate = 3000, initialDelay = 5000)
    public void print() {
        System.out.println(Thread.currentThread().getName() + " " + 1);
        System.out.println(Thread.currentThread().getName() + " " + 2);
        System.out.println(Thread.currentThread().getName() + " " + 3);
        System.out.println(Thread.currentThread().getName() + " " + 4);
    }

    @Async("threadBarExecutor")
    @Scheduled(fixedRate = 3000, initialDelay = 5000)
    public void print2() {
        System.out.println(Thread.currentThread().getName() + " " + 1);
        System.out.println(Thread.currentThread().getName() + " " + 2);
        System.out.println(Thread.currentThread().getName() + " " + 3);
        System.out.println(Thread.currentThread().getName() + " " + 4);
    }

What I would like to see is 2 or 3 of each of these threads running at the same time, but I only see each thread being run once every 3 seconds我想看到的是这些线程中的每一个同时运行 2 或 3 个,但我只看到每个线程每 3 秒运行一次

I think that you mix things : TaskExecutor/Executor configuration and the frequency rate of the tasks executed by the scheduler.我认为你混合了一些东西: TaskExecutor/Executor配置和调度程序执行的任务的频率。

This configuration means that the task will be executed every 3 seconds :此配置意味着任务将每 3 秒执行一次:

@Scheduled(fixedRate = 3000, ...)

Adding that : @Async("threadBarExecutor") just means that the Scheduler will use a specific Executor to run the tasks.添加: @Async("threadBarExecutor")仅意味着调度程序将使用特定的Executor来运行任务。

It doesn't mean that it will be executed as much as the thread pool size is not full in the configured Executor .这并不意味着它会在配置的Executor的线程池大小未满时Executor
So yes it looks normal that these two tasks be triggered every 3 seconds.所以是的,这两个任务每 3 秒触发一次看起来很正常。

If you want to run these tasks a specific number of times in parallel and every 3 seconds, @Scheduled is not enough.如果您想每 3 秒并行运行特定次数的这些任务,@ @Scheduled是不够的。
You should make the scheduler method to invoke another @Asynch method.您应该使调度程序方法调用另一个@Asynch方法。 This can be defined in the same bean or in another, you don't matter.这可以在同一个 bean 或另一个 bean 中定义,这无关紧要。

@Async("threadFooExecutor")
@Scheduled(fixedRate = 3000, initialDelay = 5000)
public void printRepeat3Times() {
    for (int i=0; i<3; i++){
         print();
    }
}


@Async("threadFooExecutor")
public void print() {
     // ...
}

Note that as these methods are annotated with @Asynch , print() invocations don't "block" the current thread and so these could be executed in parallel thanks to the ExecutorService under the hoods.请注意,由于这些方法是用@Asynch注释的, @Asynch print()调用不会“阻塞”当前线程,因此由于ExecutorService下的ExecutorService ,这些方法可以并行ExecutorService

Update: ok so based on your comments you need the following:更新:好的,根据您的评论,您需要以下内容:

public class ServiceOne {
    @Async
    public void bgTask() {
        System.out.println(Thread.currentThread().getName());
    }
}

public class ServiceTwo {
    @Autowired
    ServiceOne serviceOne;

    @Scheduled(fixedRate = 3000, initialDelay = 5000)
    public void scheduledRunner() {
        int i = 3;
        while (i-- >0 ) {
            serviceOne.bgTask();
        }
    }
}

This way the scheduled method will be executed every three seconds and it will spawn three parallel background tasks.这样,计划方法将每三秒执行一次,并且会产生三个并行的后台任务。 The inject thingie is for the AOP to work with the default weaver which would ignore one of the annotations if methods are in the same class.注入东西是为了让 AOP 与默认编织器一起工作,如果方法在同一个类中,它将忽略其中一个注释。

According to docs this is what's probably happening:根据文档,这可能是正在发生的事情:

By default, will be searching for an associated scheduler definition: either a unique TaskScheduler bean in the context, or a TaskScheduler bean named "taskScheduler" otherwise;默认情况下,将搜索关联的调度程序定义:上下文中唯一的 TaskScheduler bean,或者否则名为“taskScheduler”的 TaskScheduler bean; the same lookup will also be performed for a ScheduledExecutorService bean.还将对 ScheduledExecutorService bean 执行相同的查找。 If neither of the two is resolvable, a local single-threaded default scheduler will be created and used within the registrar.如果两者都无法解析,则会在注册器中创建和使用本地单线程默认调度程序

I think configuring a ScheduledTaskRegistrar might help:我认为配置ScheduledTaskRegistrar可能会有所帮助:

public class SchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(4); // Number of simultaneously running @Scheduled functions
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM