在Spring Batch 中开启多线程需要两个两个值:
- throttleLimit:线程数(最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目)
- taskExecutor:如果是多线程,需要将这个参数设置成线程池,默认是一个简单异步执行器
现在我们开始今天的Demo, 这个Demo实现一个SB功能,就是多线程从数据库读出来数据,然后在Writer答应出读出的对象。
话不多说,先创建一个Spring -Batch的工程(SpringBatch从入门到放弃001- HelloWorld)。
配置一个Reader,我们选用JdbcPagingItemReader,这里需要注意的是对于多线程Batch,需要考虑Reader的线程安全问题,因为在多线程情况下,会导致Reader中的 如果你还不知道那些Reader 实现线程安全的,可以参考另一文章:SpringBatch从入门到放弃006- ItemReader
?
其实实现Reader线程安全问题非常简单,我们打开JdbcPagingItemReader的源码,在Javadoc 里面是这样描述:这是一个线程安全的实现在调用open()方法之间,如果在多线程中使用,需要设置saveState=false(但是这样就会不支持重启)。
?
那么他是如何线程安全的呢?,继续看源码,在AbstractPagingItemReader.doRead()方法中我们看到了synchronized,这里是不是恍然大悟?
?
Processor 没有要求是线程安全的,所以定义成普通的就好了, Writer 要求线程安全,但是我们需求不需要线程安全,所以也定义成常规的就好了。
?
核心的配置来了,我们首先定义了一个线程池ThreadPoolTaskExecutor,然后将这个任务执行线程池定义到Step中去,在给step 设置throttleLimit 设置成5。这样就实现了多线程。
?
我们注意到reader是分页读,每次读取3个元素,chunkSize 是 5 ,代表每五次写一次,那么Reader/Processor/Writer 是怎么匹配执行的呢?这里先卖个关子后边的章节我们会说到。
定义一个Junit,查看运行结果。
?
我们可以看到多个线程在执行Job。
?
这一节只是简单介绍一个Spring Batch 多线程的配置,下个章节鹏哥将通过源码,像大家展示,Spring Batch 多线程是怎么实现的。