简体   繁体   English

如何使用线程池并行化单个石英作业?

[英]How to parallelize a single quartz job with thread pooling?

I have a quartz scheduled job in my Spring boot application to sends items from a large list to some webservices trough a method when fired in every 5 minutes.我在我的 Spring 启动应用程序中有一个石英计划作业,以在每 5 分钟触发一次时通过一种方法将大型列表中的项目发送到某些 Web 服务。

I was wondering that my sending process (single send method) can be paralelized?我想知道我的发送过程(单一发送方法)可以并行化吗? What I want is for example when 10000 items list came from db and threads from thread pool will work simultanously to send all records in that list and job will be finished after all records sent.我想要的是例如当 10000 个项目列表来自 db 并且线程池中的线程将同时工作以发送该列表中的所有记录,并且在发送所有记录后作业将完成。

What I've tried below code, I set a ThreadPoolTaskExecutor with a 5 threaded pool size.我在下面的代码中尝试过,我设置了一个ThreadPoolTaskExecutor ,它的大小为 5 个线程池。 And yet when I executed and checked the job logs it says jobs is finished with seconds but it takes a minutes to send all data.然而,当我执行并检查作业日志时,它说作业在几秒钟内完成,但发送所有数据需要几分钟。 It continue working correctly but Job seemed to finished in seconds.它继续正常工作,但工作似乎在几秒钟内完成。 It probably says the job is finished after all threads set.它可能说在所有线程设置后工作就完成了。 This is something I avoid from because needings to know job execution time and logs.这是我避免的,因为需要知道作业执行时间和日志。

@Autowired
MyService myService;

@NonTransactionalService 
public class MySenderService{

    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(5);
    taskExecutor.setMaxPoolSize(5);
    taskExecutor.initialize();

    public void sendAll(){
        List<Long> largeList = someMethod();
        largeList.stream().forEach(i -> {
            taskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    myService.send(i);
                }
            });
        }
    }
}

So, how can I run this send method with mutliple workers inside a single job?那么,如何在单个作业中使用多个工作人员运行此发送方法?
Or else is it a good practise to set multiple identical jobs for sending same list through same method?或者设置多个相同的作业以通过相同的方法发送相同的列表是一个好习惯吗?

You can try using a Flux, IMHO is the solution that requires less code:您可以尝试使用 Flux,恕我直言是需要较少代码的解决方案:

        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(5);
        taskExecutor.initialize();

        List<Integer> largeList = someMethod();
        System.out.println(largeList);
        Flux.fromStream(largeList.stream())
                .parallel(5)
                .runOn(Schedulers.fromExecutor(taskExecutor))
                .subscribe( x -> { System.out.println(x);});

        taskExecutor.shutdown();

Don't forget to shutdown the TaskExecutor, but as @M.不要忘记关闭TaskExecutor,而是作为@M。 Deinum said, it would be best to have it created elsewhere and injected in your service. Deinum 说,最好让它在别处创建并注入到您的服务中。

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

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