title: Spring-batch : How to run processor with multi thread of ItemProcessor in spring batch?
body: <p>Now my previous usage scenarios is like below:</p>
  
  <ol>
  <li>using FlatFileItemReader read input stream with .txt file line by line</li>
  <li>using ItemProcessor process per line data to invoke remote service with http</li>
  <li>using FlatFileItemWriter write result of per request into the file</li>
  </ol>
  
  <p>I would like to process remote calling with <strong>multi thread</strong> with ItemProcessor <strong>in step 2</strong></p>
  
  <p>Main flow code like below (with spring boot):</p>
  
  <pre><code>    //read data
      FlatFileItemReader&lt;ItemProcessing&gt; reader = read(batchReqRun);
  
      //process data
      ItemProcessor&lt;ItemProcessing, ItemProcessing&gt; processor = process(batchReqDef);
  
      //write data
      File localOutputDir = new File(localStoragePath+"/batch-results");
      File localOutputFile = new File(localOutputDir, batchReqExec.getDestFile());
      FlatFileItemWriter&lt;ItemProcessing&gt; writer = write(localOutputDir,localOutputFile);
  
      StepExecutionListener stepExecListener = new StepExecutionListener() {
          @Override
          public void beforeStep(StepExecution stepExecution) {
              logger.info("Job {} step start {}",stepExecution.getJobExecutionId(), stepExecution.getStepName());
          }
          @Override
          public ExitStatus afterStep(StepExecution stepExecution) {
              logger.info("Job {} step end {}",stepExecution.getJobExecutionId(), stepExecution.getStepName());
              //.......ingore some code 
              return finalStatus;
          }
      };
  
      Tasklet resultFileTasklet = new BatchFileResultTasklet(localOutputFile, httpClientService);
      TaskletStep resultFileStep = stepBuilder.get("result")
              .tasklet(resultFileTasklet)
              .listener(stepExecListener)
              .build();
  
      //create step
      Step mainStep = stepBuilder.get("run")
              .&lt;ItemProcessing, ItemProcessing&gt;chunk(5)
              .faultTolerant()
              .skip(IOException.class).skip(SocketTimeoutException.class)//skip IOException here
              .skipLimit(2000)
              .reader(reader)
              .processor(processor)
              .writer(writer)
              .listener(stepExecListener)
              .listener(new ItemProcessorListener()) //add process listener
              .listener(skipExceptionListener) //add skip exception listner
              .build();
  
  
      //create job
      Job job = jobBuilder.get(batchReqExec.getId())
              .start(mainStep)
              .next(resultFileStep)
              .build();
  
      JobParametersBuilder jobParamBuilder = new JobParametersBuilder();
  
      //run job
      JobExecution execution = jobLauncher.run(job, jobParamBuilder.toJobParameters());
  </code></pre>
  
  <p>read data like below:</p>
  
  <pre><code>private FlatFileItemReader&lt;ItemProcessing&gt; read(BatchRequestsRun batchReqRun) throws Exception {
      //prepare input file
      File localInputDir = new File(localStoragePath+"/batch-requests");
      if(!localInputDir.exists() || localInputDir.isFile()) {
          localInputDir.mkdir();
      }
      File localFile = new File(localInputDir, batchReqRun.getFileRef()+"-"+batchReqRun.getFile());
      if(!localFile.exists()) {
          httpClientService.getFileFromStorage(batchReqRun.getFileRef(), localFile);          
      }
  
      FlatFileItemReader&lt;ItemProcessing&gt; reader = new FlatFileItemReader&lt;ItemProcessing&gt;();
      reader.setResource(new FileSystemResource(localFile));
  
      reader.setLineMapper(new DefaultLineMapper&lt;ItemProcessing&gt;() {
          {
              setLineTokenizer(new DelimitedLineTokenizer());
              setFieldSetMapper(new FieldSetMapper&lt;ItemProcessing&gt;() {
                  @Override
                  public ItemProcessing mapFieldSet(FieldSet fieldSet) throws BindException {
                      ItemProcessing item = new ItemProcessing();
                      item.setFieldSet(fieldSet);
                      return item;
                  }
              });
          }
      });
  
      return reader;
  }
  </code></pre>
  
  <p>process data like below:</p>
  
  <pre><code>private ItemProcessor&lt;ItemProcessing, ItemProcessing&gt; process(BatchRequestsDef batchReqDef) {
      ItemProcessor&lt;ItemProcessing, ItemProcessing&gt; processor = (input) -&gt; {
          VelocityContext context = new VelocityContext();
          //.....ingore velocity code 
  
          String responseBody = null;
          //send http invoking
          input.setResponseBody(httpClientService.process(batchReqDef, input));
          responseBody = input.getResponseBody();
          logger.info(responseBody);
  
          // using Groovy to parse response
          Binding binding = new Binding();
          try {
              binding.setVariable("response", responseBody);
              GroovyShell shell = new GroovyShell(binding);
              Object result = shell.evaluate(batchReqDef.getConfig().getResponseHandler());
              input.setResult(result.toString());
          } catch(Exception e) {
              logger.error("parse groovy script found exception:{},{}",e.getMessage(),e);
          }
  
          return input;
      }; 
  
      return processor;
  }
  </code></pre>
  
  <p>Ignore writing file method here.</p>
  
  <p>Who can help me to implement process method with multi thread ?
  I guess spring batch read one line data and then process one line (execute ItemProcessor to invoke remote service directly)
  As We known, the speed of read one line data much more than invoking http service one time.
  So I want to read all data(or some part data) into memory (List) with single thread,and then invoke remote call with multi thread in step 2.</p>
  
  <p>(It's very easy with using java thread pool ,but i don't known implementation with spring batch)</p>
  
  <p>Please show me some code, thanks a lot!</p>