Spring batch 同一批spring是否可以同时从不同的多线程调用不同的作业参数
我们的要求是同时写入多个文件。我们使用spring批处理来编写文件,并且我们从不同的线程使用spring批处理。每个线程都有自己的应用程序上下文。因此,我们可以确保单音bean不会在多个线程之间共享。下面是我的代码片段 Spring批处理配置Spring batch 同一批spring是否可以同时从不同的多线程调用不同的作业参数,spring-batch,Spring Batch,我们的要求是同时写入多个文件。我们使用spring批处理来编写文件,并且我们从不同的线程使用spring批处理。每个线程都有自己的应用程序上下文。因此,我们可以确保单音bean不会在多个线程之间共享。下面是我的代码片段 Spring批处理配置 <bean id="reportDataReader" class="com.test.ist.batch2.rrm.batch.readers.RRMItmeReader" scope="step"> <property
<bean id="reportDataReader" class="com.test.ist.batch2.rrm.batch.readers.RRMItmeReader"
scope="step">
<property name="verifyCursorPosition" value="false" />
<property name="dataSource" ref="dataSource" />
<property name="sql" value="#{jobParameters['sqlquery']}" />
<property name="rowMapper" ref="valueMapper" />
<property name="fetchSize" value="5000" />
</bean>
<bean id="valueMapper" class="com.test.ist.batch2.rrm.batch.mappers.DBValueMapper" scope="step"></bean>
<bean id="velocityFileWritter"
class="com.test.ist.batch2.rrm.batch.writers.RRMVelocityFileWriter"
scope="step">
</bean>
<bean id="velocityEngine"
class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader = class
class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
class.resource.loader.cache = true
class.resource.loader.modificationCheckInterval = 0
</value>
</property>
</bean>
<batch:job id="rrmReportGenJob">
<batch:step id="rrmReportGenStep">
<batch:tasklet>
<batch:chunk reader="reportDataReader" writer="velocityFileWritter"
commit-interval="${reportData.reader.commit-interval}">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
下面是我们如何调用spring批处理的代码摘录
Job jobToExecute=(Job)SpringUtils.getBean(jobName);
JobParametersBuilder paramsBuilder=新的JobParametersBuilder();
//默认情况下,添加数据时间。这将有助于使用相同的参数再次启动相同的作业
paramsBuilder.addLong(“作业时间”,System.currentTimeMillis());
如果(!jobParams.isEmpty()){
//验证输入字段。
字符串sqlToUse=validator.validateInput(jobParams);
对于(Map.Entry:jobParams.entrySet()){
如果它是在一个线程中运行的,则工作正常。
当它被多个线程调用时,我们会得到下面的错误
09:09:26742错误池-1-线程-3作业。抽象作业:329-执行作业时遇到致命错误
java.lang.NullPointerException
位于org.springframework.batch.core.repository.dao.MapJobExecutionDao.synchronizeStatus(MapJobExecutionDao.java:158)
位于org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:161)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)中
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中
位于java.lang.reflect.Method.invoke(Method.java:606)
位于org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
位于org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
在org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:157)上
位于org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
位于org.springframework.transaction.interceptor.TransactionSpectSupport.invokeWithinTransaction(TransactionSpectSupport.java:262)
位于org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
在org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:179)上
位于org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
位于com.sun.proxy.$Proxy14.update(未知源)
位于org.springframework.batch.core.job.AbstractJob.updateStatus(AbstractJob.java:416)
位于org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:299)
位于org.springframework.batch.core.launch.support.simplejoblancher$1.run(simplejoblancher.java:135)
位于org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
位于org.springframework.batch.core.launch.support.simplejoblancher.run(simplejoblancher.java:128)
有谁能帮助我理解可能的错误吗?你确定MapJobExecutionDao在所有方面都是线程安全的吗?我知道,在side MapJobExecutionDao中使用了ConcurrentMap,但我不确定这是否足够。我曾经在从不同线程访问的映射中获取空指针时遇到问题问题是,其中一个线程导致了重新灰化,而当第二个线程在那个时刻访问映射时,它收到了一个空指针 您确定标识jobparameters的组合是唯一的吗?我知道,您使用System.currentTimeMillis()添加了一个参数Job\u Time,但是您知道,如果这真的在唯一的时间戳中解决了吗
您是否尝试过使用基于表的JobExecutionDao等版本?MapJobRepository不是用于生产的。它是线程安全的。如果您需要内存中作业存储库的性能(失去可重启性等),请使用内存中数据库,如HSQLDB 撇开这一点不谈,如果您使用的是线程安全组件,那么没有理由不能使用多个线程启动多个作业实例
public PetReportGenerator(ApplicationContext reportContext){
if(null == reportContext){
//if(null == appContext){
appContext=new ClassPathXmlApplicationContext("spring-batch-jobs.xml");
//}
}else{
setAppContext(reportContext);;
}
}
paramsBuilder.addString(entry.getKey(), entry.getValue());
}
}else{
throw new ReportGenerationException("Job input parameter is Empty");
}
jobexe=jobLauncher.run(jobToExecute, paramsBuilder.toJobParameters());