Reputation: 1494
I've few tasks like these:
public static String task1()
public static String task2()
public static String task3()
public static String task4()
public static String task5()
public static String task6()
I want to execute these tasks by using CompletableFuture in parallel but in async way with an executor :
CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> executeTask(), executor);
CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> executeTask(), executor);
CompletableFuture<Object> future3 = CompletableFuture.supplyAsync(() -> executeTask(), executor);
executeTask() is the method which retrieves the task to be executed, now the problem is when I start executing the above code then task1() is picked up by all the future1,future2 and future3 and task2 is picked up by all because all futures are running in parallel and in async way. What I wanted - once a task is picked up by any Future Object, is shouldn't be picked up others. How do I achieve this. Any help would be appreciated. Thanks.
Here is the code of executeTask(), what it does: There is a map (static TreeMap> map = new TreeMap<>();) which contains the method name and method to be returned as Tasks like task1, task2 etc.. Now what I am doing here: I am iterating the map and finding the that entry which doesn't have key status that means this task can be executed and returned and before returning I am putting status key so that it can't be picked up again. Now all the futures are running as async thats why all of them picking task1 together and so on.
public static Object executeTask()
{
Object result = null;
try
{
Method method = null;
for(Entry<String, HashMap<String, Method>> en : map.entrySet())
{
if(!en.getValue().containsKey("status"))
{
System.out.println("Found free task: "+en.getKey().toString());
method = en.getValue().get(en.getKey());
en.getValue().put("status", ConcurrencyPoC_CompletableFuture.class.getMethod("toString"));
break;
}
}
if(method != null)
{
System.out.println("Executing : "+method.getName());
result = (String) method.invoke(new ConcurrencyPoC_CompletableFuture());
}
}catch(Exception e)
{
e.printStackTrace();
}
return result;
}
Upvotes: 0
Views: 532
Reputation: 533790
Make the executeTask() return the actual task only once and a task which does nothing after being called more than once.
You can use synchronized, a Lock, or an AtomicReference to the task (I would do the last one)
Upvotes: 0