質問

I have a controller which executes in parallel a few jobs per request, like this:

@Controller
@RequestMapping("/uploadjob")
public class UploadJobController extends BaseController {
....
   @RequestMapping(value = "/uploadjob", method = RequestMethod.POST)
public String runupload(@ModelAttribute("uploadParameters") UploadParameters uploadParameters,
BindingResult result, HttpServletRequest request){
...
 for (Line i: lines){
     try {

           this.jobLauncher.run(this.uploadProjectDataJobNormal, jobParameters);
 }
}

At some point, the jobs reads elements from files (different in each job execution) and copy to a table but eliminating the duplicate ones.

Because the jobs are executed in parallel, in each job before insert the element we query the existing elements in the database to avoid duplicates. We want to avoid this using a:

 List<String> existingElements

But this object should be shared by all the jobs and also update by all of them at the same time, so this object need to be thread safe. I see in different questions here the solution could be use the session object (HttpSession object) to store the list and carefully access the object to avoid race conditions in the steps of the jobs.

Am I correct? Is there another alternative to achieve the same result (without change the actual workflow)?

役に立ちましたか?

解決

After trying different solutions we implement like this. We create a object to store the objects to share:

public class JobCache {

    private HashMap<TypeClass,Set<String>> ExistingNames;

    private final UUID id;
...

The id field is final to be used for synchronization the access to the attribute existingNames. And we modified the cache between the differents jobs using the next statement:

synchronized (jobCache.getId()){
            jobCache.addNames(names,TypeClass.TYPE1);
        }

We know this is not totally thread-safe but under our environment it is (because of the way how the jobs are created).

For getting the names (even if it is not needed, only to be sure, we use this:

synchronized(jobCache.getId()){
            this.names = jobCache.getExistingNames(TypeClass.TYPE1);
        }

Maybe it is not the ideal and most elegant solution but it work for us.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top