java - 子线程如何向Java中的主线程(方法)发送连续消息?
问题描述
我有一个想要相互交流的人的 HashMap,如下所示:
{zidane=[rooney, rooney, rooney, scholes, rooney], rooney=[scholes, messi, scholes], scholes=[ronaldo], ronaldo=[rooney, messi, scholes], messi=[zidane]}
在这里,密钥中的每个人都有自己的线程,他们将在其中向列表中的每个人发送消息并接收响应。
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();
}
}
该类Master
将为 HashMap 中的每个键迭代地创建一个线程。请注意,该readFile
方法只会从文本文件中读取并生成callsMap
我上面提到的输入(到变量中)。这对于这种情况并不是特别重要,所以我在这里省略了它。
我有一个SubTasks
实现Callable
接口并为每次交互创建消息的类。这个类不会创建任何额外的线程,而只是对它收到的调用者和接收者列表进行操作,如下所示:
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;
}
}
如果我直接在子线程中打印,我会得到所需的结果,因为消息是以随机顺序打印的:
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]
...
...
但我希望将这些消息打印在主方法而不是子线程中。我尝试通过连接returnMessage
and来返回消息,callerMessage
但由于我在每个线程的末尾返回,它们似乎是按顺序打印的(每对的调用-回复)如下:
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]
...
...
所以,我的问题是如何在创建后立即在主方法而不是子线程中callerMessage
打印它们?returnMessage
解决方案
它看起来像是生产者-消费者问题的经典示例,您SubTasks
是生产者,并且Master
是单个消费者。可以使用低级 Java 并发结构以多种不同的方式解决它,但最简单的一种可能是使用某种线程安全的中间队列。您可以先查看使用 Queue 的 Producer/Consumer 线程。
推荐阅读
- javascript - 从 D3 v3 改编到 v5 的代码需要额外更新才能正确呈现
- javascript - 如何测试查询器验证
- c# - 在 C# 中的 gridview 中添加时间列
- c# - 尽管登录成功,但仍触发安全日志(事件 4648)的 C# 事件处理程序
- python - 如何根据有关日期使用python的接近程度的特定条件删除重复项?
- java - JAXB XJC:如何生成 java 类
- excel - 切换工作表时保留视图
- sql - 如何使用具有多个 SELECT 子查询的 INSERT 语句,每个子查询都有自己的 WHERE 子句条件
- c++ - 在从 lua 调用的 C++ 函数中打印静态变量
- vba - 如何对查询中的字母数字文本进行排序?