首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Java中,子线程如何向主线程(方法)发送连续的消息?

在Java中,子线程如何向主线程(方法)发送连续的消息?
EN

Stack Overflow用户
提问于 2020-06-15 04:18:11
回答 1查看 170关注 0票数 0

我有一个想要彼此交流的人的HashMap,如下所示:

代码语言:javascript
运行
复制
{zidane=[rooney, rooney, rooney, scholes, rooney], rooney=[scholes, messi, scholes], scholes=[ronaldo], ronaldo=[rooney, messi, scholes], messi=[zidane]}

在这里,密钥中的每个人都有自己的线程,在这些线程中,他们将向列表中的每个人发送一条消息并接收响应。

代码语言:javascript
运行
复制
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变量中)。它对于这个上下文并不是特别重要,所以我在这里省略了它。

我有一个实现Callable接口并为每个交互创建消息的SubTasks类。这个类不会创建任何额外的线程,而只是对它收到的调用者和接收者列表进行操作,如下所示:

代码语言:javascript
运行
复制
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;
    }
}

如果我直接在子线程中打印,我会得到想要的结果,因为消息是按随机顺序打印的:

代码语言:javascript
运行
复制
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]
...
...

但我希望这些消息在main方法中打印,而不是在子线程中打印。我试图通过连接returnMessagecallerMessage来返回消息,但由于我是在每个线程的末尾返回的,所以它们似乎是按如下顺序打印的(每对调用-回复):

代码语言:javascript
运行
复制
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]
...
...

所以,我的问题是,如何在main方法中打印每个callerMessagereturnMessage,而不是在创建后立即打印它们的子线程?

EN

Stack Overflow用户

发布于 2020-06-15 04:57:09

这看起来像是生产者-消费者问题的经典例子,其中你的SubTasks是生产者,而Master是单一消费者。可以使用低级java并发构造以多种不同的方式解决此问题,但最简单的方法可能是使用某种线程安全的中间队列。您可以从查看Producer/Consumer threads using a Queue开始。

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62377733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档