我试图从数据库中读取数据,并同时在每个对象上运行进程。
我的配置如下,
@Bean
public Job job() {
return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer()).listener(new Listener(videoDao))
.flow(step1()).end().build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<VideosDTO, VideosDTO>chunk(3)
.reader(databaseVideoItemReader(null))
.processor(new Processor())
.writer(new Writer(videoDao))
.build();
}
@Bean
@StepScope
ItemReader<VideosDTO> databaseVideoItemReader(@Value("#{jobParameters[userId]}") String userId) {
logger.info("Fetching videos for userId:"+userId);
JdbcCursorItemReader<VideosDTO> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql("SELECT * FROM voc.t_videos where user_id="+userId+"AND job_success_ind='N'");
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(VideosDTO.class));
// databaseReader.open(new ExecutionContext());
ExecutionContext executionContext= new ExecutionContext();
executionContext.size();
databaseReader.open(executionContext);
return databaseReader;
}
我的项目处理如下,
@Override
public VideosDTO process(VideosDTO videosDTO) throws Exception {
log.info("processing........" + videosDTO.getVideoUrl());
try {
Process p = Runtime.getRuntime()
.exec("C:\\Program Files\\Git\\bin\\bash.exe " + "D:\\DRM\\script.sh " + videosDTO.getVideoUrl());
// .exec("D:\\PortableGit\\bin\\bash.exe
// D:\\Vocabimate_Files\\script.sh "+videosDTO.getVideoUrl());
// Thread.sleep(1000);
Thread.sleep(1000);
p.destroy();
try {
p.waitFor();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try (InputStream is = p.getErrorStream()) {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
}
try (InputStream is = p.getInputStream()) {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
}
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
return videosDTO;
}
作者如下:
@Override
public void write(List<? extends VideosDTO>videosList) throws Exception {
for(VideosDTO vid:videosList){
log.info("writting...."+vid.getVideoUrl());
}
}
假设首先从数据库中获取3个对象,则此代码 完成第一个对象的过程,第二个对象比第三个对象 开始写我想同时在三个对象上运行进程 同时执行写操作。
有什么办法吗?
答案 0 :(得分:1)
在不深入了解自定义阅读器/处理器/书写器的详细信息的情况下,我认为您要寻找的是a multi-threaded Step。
如上面链接的文档中所述,为了使您的步骤成为多线程(意味着在单独的线程中读取/处理/写入每个块),您首先需要注册SimpleAsyncTaskExecutor
:
@Bean
public TaskExecutor taskExecutor(){
return new SimpleAsyncTaskExecutor("myAsyncTaskExecutor");
}
,然后在您的Step的构建器中注册此任务执行器:
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<VideosDTO, VideosDTO>chunk(3)
.reader(databaseVideoItemReader(null))
.processor(new Processor())
.writer(new Writer(videoDao))
//making the Step multi-threaded
.taskExecutor(taskExecutor())
.build();
}
答案 1 :(得分:1)
使用@dimitrisli建议的多线程步骤是可行的方法。除此之外,另一种方法是使用AsyncItemProcessor
(与AsyncItemWriter
结合使用)。
可以在以下位置找到类似的用例(从处理器异步调用剩余端点):https://stackoverflow.com/a/52309260/5019386,其中提供了更多详细信息。
希望这会有所帮助。