I have a spring Batch job that basically reads from a file, processes each line and writes to an output (another file). Since the processing step is costly I want to have it run in multiple threads, but since the reading and writing steps are using files, those steps must be run on a single thread. I ended up having 3 flows, each running in parallel, with one step each, synchronized on 2 BlockingQueues. The read step reads from the file and writes to one queue. The processing step is multi-threaded and reads from the queue, processes and writes to another queue. The write step, reads from the second queue and writes the output to another file.
It works pretty well, except that i can't find a clean and 'fast' way to stop the job when everything is done. Right now i'm using 'poll' with a timeout on both queues, and assuming that if no item is present for some amount of seconds, then we're done. This delays the job termination by the specified amount of seconds, and i can't use a very small amount of time because by some external force (like machine load) the job can suffer delays.
I tried using something like a Poison Pill, but the problem is that if i override the 'doRead' method on the FlatFileItemReader to return a Poison Pill when it gets a 'null' (signifying end-of-file) then this reader will never end and the job never terminates.
Does anyone have a suggestion? From the documentation i know that i could probably just put a "synchronized" on the reader from the read Step (file) and on the writer in the Write Step (file), but i'd really prefer a different solution.