Multithreading for array in Java

732 Views Asked by At

So, the scenario is like:

//Some code...

public Map<String, String> someFunction() {
    for (final UserDetail user : userDetailList) {
        // the following (below) code runs in background thread
        // long running task
        new RecordPersonalisedDao().getPendingRecordsForUid(user.getuId(), new RecordPersonalisedDao.OnResultFetched() {
            @Override
            public void onResult(Result result) {
                // callback after the user is processed
                // put some parameter from result to map
                map.put(user.getName(), result.getTotal());
            }
        });
    }
    // return map only after all users are processed
    return map;
}

As mentioned in the comment of above piece of code, I want the final map to be returned only after the entire list of user is processed.

I cannot change the functionality of RecordPersonalisedDao#getPendingRecordsForUid so as to make it run in the main thread only.

How do I achieve this in java ?

Edit: This type of problem can be faced in general. So, I want to understand the solution for the same in java.

To put my question simply, I want behaviour like

  • Run this code in background for all members in the array, and once it's done, send a callback.

(Roughly like)

[list_of_some_data]
    .forEach( run this function )
    .after(after the function is run in background for  all members of list - return some value)
2

There are 2 best solutions below

4
On

Before the loop, create a CountdownLatch with a count equal to the user list length. Inside the result handler, count down after updating the map. After the loopawait() the latch to be counted down, then return.

0
On
public Map<String, String> someFunction() {
    CountDownLatch cdl = new CountDownLatch(userDetailsList.size());
    for (final UserDetail user : userDetailList) {
        // the following (below) code runs in background thread
        // long running task
        new RecordPersonalisedDao().getPendingRecordsForUid(user.getuId(), new RecordPersonalisedDao.OnResultFetched() {
            @Override
            public void onResult(Result result) {
                // callback after the user is processed
                // put some parameter from result to map
                map.put(user.getName(), result.getTotal());

                //We're done grabbing the results.. count down.
                cdl.countDown();
            }
        });
    }

    //Block this thread until all the results are in.
    cdl.await();

    return map;
}