I am writing a program that does some batch processing. Batch items can be processed independently of each other, and we want to minimize the total processing time. Thus, instead of iterating over each element in the package one at a time, I use the ExecutorService and pass Callable objects to it:
public void process(Batch batch) { ExecutorService execService = Executors.newCachedThreadPool(); CopyOnWriteArrayList<Future<BatchElementStatus>> futures = new CopyOnWriteArrayList<Future<BatchElementStatus>>(); for (BatchElement element : batch.getElement()) { Future<MtaMigrationStatus> future = execService.submit(new ElementProcessor(batch.getID(), element)); futures.add(future); } boolean done = false; while (!done) { for (Future<BatchElementStatus> future : futures) { try { if (future.isDone()) { futures.remove(future); } } catch (Exception e) { System.out.println(e.getMessage()); } if (futures.size() == 0) { done = true; } } } }
We want to be able to enable batch processing. Since I do not use a loop, I cannot just check at the top of each loop if the cancel flag is set.
We are using a JMS theme with which BatchProcessor and ElementProcessor will listen to report that the package has been canceled.
There are several steps to the ElementProcess () call, after which some of them can be safely stopped, but there is no return point. The class has this basic design:
public class ElementProcessor implements Callable, MessageListener { private cancelled = false; public void onMessage(Message msg) { // get message object cancelled = true; } public BatchElementStatus call() { String status = SUCCESS; if (!cancelled) { doSomehingOne(); } else { doRollback(); status = CANCELLED; } if (!cancelled) { doSomehingTwo(); } else { doRollback(); status = CANCELLED; } if (!cancelled) { doSomehingThree(); } else { doRollback(); status = CANCELLED; } if (!cancelled) { doSomehingFour(); } else { doRollback(); status = CANCELLED; } // After this point, we cannot cancel or pause the processing doSomehingFive(); doSomehingSix(); return new BatchElementStatus("SUCCESS"); } }
I am wondering if there is a better way to check if a package / element has been canceled, except for calls to the lock method / code blocks in the call method in if(!cancelled) .
Any suggestions?
sdoca source share