HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Calling a method in parallel which returns the future

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
themethodfutureparallelreturnswhichcalling

Problem

I have an async method which calls my Task class while my Task class does all the work:

private ExecutorService executor = Executors.newFixedThreadPool(10);

    @Override
    public Future executeAsync(DataKey key) {
        Future future = null;

        try {
            Task task = new Task(key, restTemplate);
            future = executor.submit(task); 
        } catch (Exception ex) {
            // logging exception here
        }

        return future;
    }


Here is my Task class which does all the work:

public class Task implements Callable {

    private DataKey key;
    private RestTemplate restTemplate;

    public Task(DataKey key, RestTemplate restTemplate) {
        this.key = key;
        this.restTemplate = restTemplate;
    }

    @Override
    public DataResponse call() throws Exception {
        // some code here
    }
}


Now I need to call executeAsync method in parallel and then make a List object and return it:

@Override
public List executeSync(DataKey key) {
    List responseList = new ArrayList();

    // make a List of DataKey using single key passed to this method.       
    List keys = new ArrayList();

    // here keys max size will be three
    List futures = new ArrayList<>(keys.size());
    for(DataKey key : keys) {
        Future future = executeAsync(key);
        futures.add(future);
    }

    for (Future future : futures) {
        try {
            responseList.add(future.get(300, TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            // do something
        }
    }
    return responseList;
}


My intention is to call executeAsync method in parallel and return back responseList object. I mean I want to execute call method of my Task class in parallel for each of the key object so if I have three key object in keys list, then I want to execute call method for each key in parallel and then make a List object and return it.

Since I don't want to wait 300 Milliseconds

Solution

An executor service will be able to do a invokeAll with a timeout and return a set of futures holding all the values or return when the timeout expires.

This means that your executeAsync should take a set of keys and build all the tasks from those at once and then submit the tasks as a batch:

@Override
public List> executeAsync(Collection keys,  long timeout, TimeUnit unit) {
    List tasks = new ArrayList<>(keys.size());
    for(DataKey key : keys){
        tasks.add(new Task(key, restTemplate));
    }

    return executor.invokeAll(tasks, timeout, unit);
}

@Override
public List executeSync(DataKey key) {
    List responseList = new ArrayList();

    // make a List of DataKey using single key passed to this method.       
    List keys = new ArrayList();

    List futures = executeAsync(keys, 300, TimeUnit.MILLISECONDS);

    for (Future future : futures) {
        try {
            if(future.isDone())
                responseList.add(future.get());
            //otherwise future didn't complete in the 300 milliseconds
        } catch (Exception e) {
            // do something
        }
    }
    return responseList;
}

Code Snippets

@Override
public List<Future<DataResponse>> executeAsync(Collection<DataKey> keys,  long timeout, TimeUnit unit) {
    List<Task> tasks = new ArrayList<>(keys.size());
    for(DataKey key : keys){
        tasks.add(new Task(key, restTemplate));
    }

    return executor.invokeAll(tasks, timeout, unit);
}


@Override
public List<DataResponse> executeSync(DataKey key) {
    List<DataResponse> responseList = new ArrayList<DataResponse>();

    // make a List of DataKey using single key passed to this method.       
    List<DataKey> keys = new ArrayList<DataKey>();

    List<Future> futures = executeAsync(keys, 300, TimeUnit.MILLISECONDS);


    for (Future<DataResponse> future : futures) {
        try {
            if(future.isDone())
                responseList.add(future.get());
            //otherwise future didn't complete in the 300 milliseconds
        } catch (Exception e) {
            // do something
        }
    }
    return responseList;
}

Context

StackExchange Code Review Q#113406, answer score: 5

Revisions (0)

No revisions yet.