I am experiencing the following problem. In a simplest way put I have a servlet and a java class in my web app. Now the java class iterates over the list applying some logic to each element. I also keep a counter to keep track of handled elements. I propagate the counter value to another class that servlet has access to via a setter. From my servlet I do AJAX calls to retrieve the number of handled element and show a progress bar.
int counter = 0;
...
for(SecurityForWorkflow securityForWorkflow : newSecuritiesForWorkflow) {
...
WorkflowManager.getInstance().setProcessedSecurities(counter);
counter++;
...
}
The problem is that the progress bar is not smooth, it may go from 1 to 56 to 100. My guess is that JIT somehow optimizes the flow by seeing that no one accesses(gets) the counter and moves the increment out of the loop. I came to this conclusion since When debugging the loop everything goes smooth(I assume JIT cant change the flow when debugging) but when I run it and output the values into a log file with timestamps, the counter increments from 0 to the overall value instantaneously/simultaneously even thou the loop runs for 20 second(170 iterations case).
My question is whether it is possible to disable JIT optimizations for a code segment(e.g. via annotations, but googling suggests that it is not) or maybe enforce non-optimization via a language construct/trick(i tried declaring the variable static, volatile, putting the loop in a synchronized block, calling the setter within a newly spawned thread every time, putting the setter in the finally block of a try-catch and some more I cant remember now and works if I put a Thread.sleep(1000) in the loop).
UPDATE: Here is the code of the loop
Also I updated the WorkflowManager.getInstance().setProcessedSecurities(counter);
with WorkflowManager.getInstance().incProcessedSecurities();
bit the result is the same
for(SecurityForWorkflow securityForWorkflow : newSecuritiesForWorkflow) {
ManualInteractionEntity manualInteractionEntity = null;
BondEntityStatus createdBond = null;
LegEntity createdLeg = null;
isin = securityForWorkflow.getIsin();
try {
automatedSecurityBuildingStatus = securityBuilder.createBondEntity(
isin, businessDay);
if(automatedSecurityBuildingStatus.getBondEntityStatus()
.getAssetType() != null
&& automatedSecurityBuildingStatus.getBondEntityStatus()
.getEcbStatus() != null) {
createdBond = automatedSecurityBuildingStatus.getBondEntityStatus();
}
else {
removeFromSecuritiesForWorkflow.add(securityForWorkflow);
}
} catch(Exception e) {
NabsLogger.getInstance().log(Level.WARNING, String.format("Exception"
+ " when creating security with isin: %s", isin), e);
continue;
}finally{
WorkflowManager.getInstance().incProcessedSecurities();
}
try {
createdLeg = createdBond.getLegEntities().get(0);
} catch (Exception e) {
createdLeg = createdBond.getLegEntityStatus();
}
if (createdBond.getSetupStatus().equals(
Constants.MANUAL_INTERACTION_NEEDED)) {
manualInteractionEntity = new ManualInteractionEntity();
securityForWorkflow.addStatus(
SecurityForWorkflow.STATUS_MANUAL_INTERACTION_NEEDED);
manualInteractionEntity.setId(createdBond.getId());
manualInteractionEntity.setCreation(true);
Set<String> manualInteractionFields = automatedSecurityBuildingStatus
.getManualInteractionRuleResults().keySet();
manualInteractionEntity.setManualInteractionFields(
new ArrayList<String>(manualInteractionFields));
manualInteractionEntities.add(manualInteractionEntity);
} else if (createdBond.getSetupStatus().equals(
Constants.CREATED_AUTOMATICALLY)) {
securityForWorkflow.addStatus(
SecurityForWorkflow.STATUS_AUTOMATICALLY_BUILT);
}
PaymentDateCalculatorModel paymentDateCalculatorModel =
new PaymentDateCalculatorModel();
paymentDateCalculatorModel.setAllDates(createdBond);
PaymentProfileCalculatorModel paymentProfileCalculatorModel =
new PaymentProfileCalculatorModel();
paymentProfileCalculatorModel.setAllPayments(createdBond);
entities.add(createdBond);
legs.add(createdLeg);
}
Thanks.
Try making the counter
volatile
or even better anAtomicInteger
.