Issue
I have a scenario where I am populating a DTO object using some logic. This DTO object has 8 objects. All these 8 objects are independent of each other. So, in my service class, I am currently calling all 8 setters methods in sequence and then returning the DTO object.
public PipelineAndActivitiesForDashboard customerpipeline(DashboardData payload) throws Exception
{
PipelineAndActivitiesForDashboard dashboardPipelineReturnData = new PipelineAndActivitiesForDashboard();
List<LeadActivity> data = new ArrayList<LeadActivity>();
Date fromdate = payload.getFromDate();
Date todate = payload.getToDate();
log.info("fromdate : " + fromdate + " todate: " + todate);
data = lRepo.getActivity(fromdate, todate);
log.info("Fetching Lead Generated Stats");
dashboardPipelineReturnData.setLeadGenerated(// some logic to fetch values from data );
log.info("Fetching Activities Created Stats");
dashboardPipelineReturnData.setActivitiesCreated(// some logic to fetch values from data);
log.info("Fetching Property Visit Stats");
dashboardPipelineReturnData.setTotalPropertyVisit(// some logic to fetch values from data);
log.info("Fetching Deal close Stats");
dashboardPipelineReturnData.setDealClosed(// some logic to fetch values from data);
log.info("Fetching deal lost Stats");
dashboardPipelineReturnData.setDealLost(// some logic to fetch values from data);
log.info("Fetching today's activities Stats");
dashboardPipelineReturnData.setTodaysActivities(some logic to fetch values from data);
log.info("Fetching pending activities Stats");
dashboardPipelineReturnData.setPendingActivities(some logic to fetch values from data);
log.info("Fetching upcoming activities Stats");
dashboardPipelineReturnData.setUpcomingActivities(some logic to fetch values from data);
return dashboardPipelineReturnData;
}
Each of the logic takes around 5 seconds of processing. So, executing 8 in sequence is making the response slow.
I am looking for some help in identifying the java or spring concept that can be used here to trigger these 8 setter methods in parallel.
So, flow should be
- All the 8 setters should be triggerred in parallel
- Control should not reach to return statement until all 8 setter methods execution is complete
Solution
You can use Multithreading with cyclic barrier. Cyclic Barriers are used in programs in which we have a fixed number of threads that must wait for each other to reach a common point before continuing execution. You can create a Runnable job for every setter you need to process. Since we are using Cyclic barrier all the threads will run in parallel and will wait until all have completed the execution, before you can return the final object.
Pseudocode -
public class Test {
public static void main(String[] args) {
ExecutorService executors = Executors.newFixedThreadPool(8);
CyclicBarrier barrier = new CyclicBarrier(8);
executors.submit(new SetLeadGenerated(barrier,dashboardPipelineReturnData));
//submit the runnable job for all other setter methods
// at this point dashboardPipelineReturnData will be updated with all the data
}
}
class SetLeadGenerated implements Runnable {
private CyclicBarrier barrier;
private PipelineAndActivitiesForDashboard dashboardPipelineReturnData;
public SetLeadGenerated(CyclicBarrier barrier,PipelineAndActivitiesForDashboard dashboardPipelineReturnData) {
this.dashboardPipelineReturnData = dashboardPipelineReturnData;
this.barrier = barrier;
}
@Override
public void run() {
try {
//do your task here
dashboardPipelineReturnData.setLeadGenerated(// some logic to fetch values from data );
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
finally {
barrier.await();
}
}
}
Once the number of threads that called await() equals numberOfThreads, the barrier then gives a way for the waiting threads
Answered By - Shubham Chopra