I have a situation where my code needs to do to huge calculation for each "fund" in a list.
I can do it in sequential order and it works perfectly fine, however it takes lot of time. For 1 fund it takes about 13-15 minuntes. I have to run this for 50 funds and it take huge amount of time.
The code snippet is something like this:
List<Map<String, Object>> fundsList = getTheListOfFunds()
Iterator<Map<String, Object>> itr = fundsList.listIterator();
List<Map<String, Object>> expectedDataList = new ArrayList<>();
while (itr.hasNext()) {
Map<String, Object> finalData = doCalc(parameter1, parameter2, parameter3);
expectedDataList.add(finalData);
}
I am very new to multi-threading. Can someone please help me to refactor the code so that the calculation (doCalc
) can be done in multiple threads instead of a single thread?
CodePudding user response:
You can use the Executors.newFixedThreadPool(int)
method to get an ExecutorService to submit tasks to.
Each task that you submit to the thread pool will return a Future
, which you can maintain a list of and retrieve the returned value at a later time.
Here's an example:
// Create a new fixed thread pool with a predefined number of threads.
final ExecutorService service = Executors.newFixedThreadPool(10);
// Create a list of Future objects to retrieve later.
List<Future<Map<String, Object>>> futures = new ArrayList<>();
// Loop through your list and for each iteration, submit your task
// to the Executor service, and add the result to your Future list.
for (Map<String, Object> fund: fundsList) {
futures.add(service.submit(() -> doCalc(/* parameters */)));
}
// Loop through the Future list and call the .get() method to
// retrieve the computed value.
for (Future<Map<String, Object>> future: futures) {
try {
final Map<String, Object> finalData = future.get();
expectedDataList.add(finalData);
} catch (InterruptedException | ExecutionException e) {
// log or throw error
}
}
CodePudding user response:
Thank you all for your answers and comments. Special thanks to @blacktide and @federOnline for putting us in the right direction. I work with Brajesh and here is what we wrote, please correct us for any issues.
public class MyThreadTest {
public static void main(String[] args) {
final ExecutorService service = Executors.newFixedThreadPool(3);
// Create a list of Future objects to retrieve later.
List<Future<Integer>> futures = new ArrayList<>();
// Loop through your list and for each iteration, submit your task
// to the Executor service, and add the result to your Future list.
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] b = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(int i=0; i<a.length; i ) {
int finalI = i;
futures.add(service.submit(() -> add(a[finalI], b[finalI])));
}
// Loop through the Future list and call the .get() method to
// retrieve the computed value.
List<Integer> list = new ArrayList<>();
for (Future<Integer> future: futures) {
try {
int finalData = future.get();
if(future.isDone()) {
list.add(finalData);
}
} catch (InterruptedException | ExecutionException e) {
// log or throw error
}
}
System.out.println(list.size());
service.shutdown();
}
public static int add(int a, int b) {
System.out.println(Thread.currentThread().getName());
return a b;
}
}