Parallelstream.ForEach()双项

时间:2016-11-12 16:30:05

标签: java asynchronous parallel.foreach

我有一个软件可以根据excel文件生成SOAP请求,然后通过电子邮件发送结果。

由于请求的可能大小,我并行执行soap-request-handling。以下代码处理上述内容。

    public void HandleData() {
    List<NodeAnalysisReply> replies = Collections.synchronizedList(new ArrayList<>());
    new Thread(() -> {
        List<NodeAnalysisRequest> requests;
        SOAPMessageFactory factory = new SOAPMessageFactory();
        SOAPResponseParser parser = new SOAPResponseParser();

        try {
            requests = new ExcelParser().parseData(file);
            requests.parallelStream().forEach((request) -> {
                try {
                    SOAPMessage message = factory.createNodeRequestMessage(
                            new RequestObject(requestInfoFactory.makeInfo(trackingID), request));
                    SOAPMessage response = new SoapConnector(server.getUrl()).executeRequest(message);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.writeTo(out);
                    NodeAnalysisReply curReply = parser.ParseXMLResponse(out.toString(), request);
                    synchronized (replies) {
                        System.out.println("Adding: " + curReply.getRequest().toString());
                        replies.add(curReply);
                    }
                } catch (UnsupportedOperationException | SOAPException | IOException e) {
                    handleSoap(e.getMessage());
                }
            });
        } catch (IOException e) {
            handleBadParse();
        }

        try {
            for(NodeAnalysisReply reply : replies){
                System.out.println("Data: " + reply.getRequest().toString());
            }
            mailer.SendEmail("Done", email, replies);
        } catch (MessagingException e) {
            e.printStackTrace();
        }

    }).start();
}

当我使用两段数据运行代码时,会发生以下情况:

Adding: Søndergade 52 6920 // OK
Adding: Ternevej 1 6920 // OK

Data: Ternevej 1 6920 // What
Data: Ternevej 1 6920 // WHAT..
are equal? true

所以尽管它将两个项目都添加到列表中,但似乎最后一个项目占据了两个位置。那怎么回事,我该怎么解决呢? - 我确实错过了Parrallel.ForEach()表单C#!

编辑:根据要求,NodeAnalysisReply的代码。

public class NodeAnalysisReply {

 public ReplyInfo getReplyInfo() {
  return replyInfo;
 }

 public void setReplyInfo(ReplyInfo replyInfo) {
  this.replyInfo = replyInfo;
 }

 public List < nodeAnalysisListDetails > getNodeAnalysisListDetails() {
  return nodeAnalysisListDetails;
 }

 public void setNodeAnalysisListDetails(List < nodeAnalysisListDetails > nodeAnalysisListDetails) {
  this.nodeAnalysisListDetails = nodeAnalysisListDetails;
 }

 public void addNodeAnalysisListDetail(nodeAnalysisListDetails nodeAnalysisListDetails) {
  this.nodeAnalysisListDetails.add(nodeAnalysisListDetails);
 }
 ReplyInfo replyInfo;
 public String getFormattedXML() {
  return formattedXML;
 }

 public void setFormattedXML(String formattedXML) {
  this.formattedXML = formattedXML;
 }
 String formattedXML;
 public NodeAnalysisRequest getRequest() {
  return request;
 }

 public void setRequest(NodeAnalysisRequest request) {
  this.request = request;
 }
 NodeAnalysisRequest request;

 List < nodeAnalysisListDetails > nodeAnalysisListDetails = new ArrayList < > ();

}

1 个答案:

答案 0 :(得分:0)

synchronized (replies) {
     System.out.println("Adding: " + curReply.getRequest().toString());
     replies.add(curReply);
}

流中的lambda中的上述代码称为副作用,根本不鼓励。

你应该做的事情如下。

replies.addAll(requests.parallelStream().map((request) -> {
                try {
                    SOAPMessage message = factory.createNodeRequestMessage(
                            new RequestObject(requestInfoFactory.makeInfo(trackingID), request));
                    SOAPMessage response = new SoapConnector(server.getUrl()).executeRequest(message);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.writeTo(out);
                    NodeAnalysisReply curReply = parser.ParseXMLResponse(out.toString(), request);
                    return curReply;
                } catch (UnsupportedOperationException | SOAPException | IOException e) {
                    handleSoap(e.getMessage());
                    return null;
                }
            })
            .filter(curReply -> curReply != null)
            .collect(Collectors.toList())
        );

在上面的代码中,您首先将每个request映射到NodeAnalysisReply,然后仅过滤非空值,最后将其收集到列表中以及所有replies列表中的值