I have a HashMap of people who want to communicate with each other as follows:
{zidane=[rooney, rooney, rooney, scholes, rooney], rooney=[scholes, messi, scholes], scholes=[ronaldo], ronaldo=[rooney, messi, scholes], messi=[zidane]}
Here, each person in the key will have their own threads in which they will send a message to each person in their list and receive a response.
public class Master {
public Map callsMap = new HashMap<String, List>();
public static void main(String[] args) throws InterruptedException, ExecutionException {
Master m = new Master();
m.readFile();
ExecutorService executorService = Executors.newFixedThreadPool(6);
List<Future<String>> returnFutures = new ArrayList<>();
Iterator<Map.Entry<String, List>> it = m.callsMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, List> pair = it.next();
String caller = pair.getKey();
List receiverList = pair.getValue();
returnFutures.add(executorService.submit(new SubTasks(caller, receiverList) ));
}
while(executorService.awaitTermination(1, TimeUnit.SECONDS));
for(Future<String> returnFuture: returnFutures){
System.out.println(returnFuture.get());
}
executorService.shutdown();
}
}
The Master
class will iteratively create a thread for every key in the HashMap. Please note that the readFile
method will just read from a text file and produce the input (into callsMap
variable) I have mentioned above. It is not particularly important for this context so I have omitted it here.
I have the SubTasks
class which implements the Callable
interface and creates messages for each interaction. This class will not create any additional threads but just operate on the caller and receiver list it received as follows:
import java.util.List;
import java.util.concurrent.Callable;
public class SubTasks implements Callable<String> {
private String caller;
private List receiverList;
private volatile String returnMessage;
private volatile String callerMessage;
private volatile String str = "";
SubTasks(String s, List l){
caller = s;
receiverList = l;
}
@Override
public String call (){
for (int i = 0; i < receiverList.size(); i++) {
callerMessage = receiverList.get(i)+" received intro message from "+caller +" ["+System.currentTimeMillis()+"]";
//System.out.println(callerMessage);
returnMessage = caller+" received reply message from "+receiverList.get(i) +" ["+System.currentTimeMillis()+"]";
//System.out.println(returnMessage);
str = str + callerMessage +"\n"+ returnMessage +"\n";
}
return null;
}
}
If I directly print in the child threads, I get the desired result as the messages are being printed in random order:
rooney received intro message from zidane [1592165414388]
ronaldo received intro message from scholes [1592165414388]
scholes received intro message from rooney [1592165414388]
rooney received intro message from ronaldo [1592165414389]
zidane received intro message from messi [1592165414389]
scholes received reply message from ronaldo [1592165414434]
zidane received reply message from rooney [1592165414434]
...
...
But I want these messages to be printed in the main method instead of the child threads. I tried to return the messages by concatenating the returnMessage
and callerMessage
but since I return at the end of each thread, they appear to be printed sequentially (call-reply for each pair) as follows:
rooney received intro message from zidane [1592165584566]
zidane received reply message from rooney [1592165584614]
rooney received intro message from zidane [1592165584632]
zidane received reply message from rooney [1592165584632]
rooney received intro message from zidane [1592165584632]
zidane received reply message from rooney [1592165584632]
...
...
So, my question is how do I print each callerMessage
and returnMessage
in the main method instead of the child threads as soon as they are created?