【发布时间】:2021-03-16 09:48:37
【问题描述】:
我已经编写了 ItemWriter 的异步版本来异步写入我的项目:
public class AsyncListItemWriter<T> implements ItemStreamWriter<T>, InitializingBean {
private ItemWriter<T> delegate;
private TaskExecutor taskExecutor = new SyncTaskExecutor();
public void afterPropertiesSet() throws Exception {
Assert.notNull(delegate, "A delegate ItemWriter must be provided.");
}
public void setDelegate(ItemWriter<T> delegate) {
this.delegate = delegate;
}
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).open(executionContext);
}
}
@Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).update(executionContext);
}
}
@Override
public void close() throws ItemStreamException {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).close();
}
}
@Override
public void write(List<? extends T> items) {
StepExecution stepExecution = getStepExecution();
taskExecutor.execute(() -> {
if (stepExecution != null) {
StepSynchronizationManager.register(stepExecution);
}
try {
delegate.write(items);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stepExecution != null) {
StepSynchronizationManager.close();
}
}
});
}
private StepExecution getStepExecution() {
StepContext context = StepSynchronizationManager.getContext();
if (context == null) {
return null;
}
StepExecution stepExecution = context.getStepExecution();
return stepExecution;
}
}
配置:
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(64);
executor.setQueueCapacity(64);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("MultiThreaded-");
return executor;
}
@Bean
public ItemWriter<STModel> writer(){
return items -> {
Thread.sleep(1000);
System.out.println("Writing...");
for(STModel c : items) {
System.out.println("######### Writer : ------> " + c + " inside size : " + c.relation.size() + ", On : " +Thread.currentThread().getName());
}
};
}
@Bean
public AsyncListItemWriter<STModel> asyncWriter() throws Exception {
AsyncListItemWriter<STModel> asyncItemWriter = new AsyncListItemWriter<>();
asyncItemWriter.setDelegate(writer());
asyncItemWriter.setTaskExecutor(taskExecutor());
asyncItemWriter.afterPropertiesSet();
return asyncItemWriter;
}
@Bean
public Step sampleStep() throws Exception{
return stepBuilderFactory.get("processingStep")
.<STModel, STModel>chunk(10)
.reader(itpReader())
.writer(asyncWriter())
.build();
}
@Bean
public Job job() throws Exception{
return jobBuilderFactory.get("job")
.start(sampleStep())
.build();
}
在阅读完所有文件后,我收到了这个日志(文件在主线程上读取):
同时读取 ---->STModel(tripId=109138356-1_459178)
同读时---->STModel(tripId=109138356-1_459178)
虽然相同读取 ---->null
读取---->null,打开:main
2021-03-16 10:38:48.409 INFO 17042 --- [main] os.batch.core.step.AbstractStep:步骤:[processingStep] 在 337 毫秒内执行
2021-03-16 10:38:48.412 INFO 17042 --- [main] o.s.b.c.l.support.SimpleJobLauncher:作业:[SimpleJob:[name=job]] 已完成,参数如下:[{}] 和以下状态:[已完成] 在 349 毫秒内
写作...
######### 编写器:------> STModel(tripId=109138355-1_459164) 内部大小:2,开启:MultiThreaded-1
######### 编写者:------> STModel(tripId=109138355-1_459165) 内部大小:1,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=109138355-1_459166) 内部大小:1,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=109138355-1_459167) 内部大小:1,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=109138355-1_459168) 内部大小:2,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=113507833-1_38959) 内部尺寸:23,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=113507835-1_38960) 内部尺寸:23,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=113507852-1_38961) 内部尺寸:23,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=113507863-1_38962) 内部尺寸:23,开启:MultiThreaded-1
######### 编写器:------> STModel(tripId=113507871-1_38963) 内部尺寸:23,开启:MultiThreaded-1
写作...
######### 编写器:------> STModel(tripId=113507882-1_38964) 内部大小:23,开启:MultiThreaded-2
######### 编写器:------> STModel(tripId=113507890-1_38965) 内部尺寸:23,开启:MultiThreaded-2
######### 编写器:------> STModel(tripId=113507900-1_38966) 内部尺寸:23,开启:MultiThreaded-2
######### Writer : ------> STModel(tripId=113507911-1_38967) inside size : 23, On : MultiThreaded-2
如您所见,spring batch 过早检测到 steap 的结束,就在读取操作之后。
如何告诉 spring batch 步骤结束是在所有写入任务完成之后?
【问题讨论】:
-
异步在后台运行,所以只要一切都在后台,对于 Spring Batch,写入已经完成。如果这不是您想要的,请不要使用异步,或者编写一个适当的异步编写器来等待所有任务完成。
-
是否有另一种方法可以通过仅使用 spring 批处理组件来执行此异步写入?
-
如果仍然要等待所有线程,为什么还需要异步写入。
-
我想在处理完所有项目后发送邮件。现在邮件发送得太早了
-
如果您仍然要等待它,为什么还需要异步写入?它增加了什么?
标签: java spring spring-batch