Home > front end >  Convert a single-threaded calculation to multi-threaded in Java
Convert a single-threaded calculation to multi-threaded in Java

Time:10-11

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;
}

}

  • Related