【问题标题】:How to use multi-threading to parallellize a for loop in Java?如何使用多线程并行化 Java 中的 for 循环?
【发布时间】:2019-05-22 23:39:18
【问题描述】:

我正在编写一个代码,它从文件中挑选多个 API 调用详细信息并逐个执行这些详细信息,并在 ArrayList 中提供响应数据。以下是我当前的代码。

ArrayList<APICallDetails> apiCallDetailsArray = new ArrayList<>();
APICallDetails apiCallDetails = new APICallDetails();
for (count= 1; count <= callsCount; count++){
        try{
            apiCallDetails = new APICallDetails();
            apiCallDetails.setName(property.getPropertyReader(callName+"_"+count+"_Name", propsFile));
            apiCallDetails.setHost(marketConfigs.getRawJson().get(property.getPropertyReader(callName+"_"+count+"_Host", propsFile)).toString().replaceAll("\"", ""));
            apiCallDetails.setPath(property.getPropertyReader(callName+"_"+count+"_Path", propsFile));
            apiCallDetails.setMethod(property.getPropertyReader(callName+"_"+count+"_Method", propsFile));
            apiCallDetails.setBody(property.getPropertyReader(callName+"_"+count+"_Body", propsFile));

            apiCallDetails = sendAPIRequest.mwRequestWithoutBody(apiCallDetails, marketConfigs);
            BufferedWriter out = null;
            try {
                out = new BufferedWriter ( new FileWriter ( "C:\\file"+count+".html"));
                    out.write("something");
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error(new Date()+" - Error in "+getClass()+".apiCallRequester() flow: "+e.toString());
                }

            apiCallDetailsArray.add(apiCallDetails);

        }catch(NullPointerException e){
            e.printStackTrace();
            logger.error(new Date()+" - Error in "+getClass()+".apiCallRequester() flow: "+e.toString());
        }
    }

由于有更多的 API 调用,这是所有调用的响应时间的总和。我希望这些调用并行运行并将响应数据存储在一个 ArrayList 中,我可以进一步使用它。 我是Java新手,有人可以帮我吗?

【问题讨论】:

  • 查看 CompletableFuture。
  • 这个for循环也有点过时了。查看 Streams API 以获得更具表现力的迭代构造。 (奖金,流是微不足道的并行化)。请注意,Java 对象并非都是固有的线程安全的,sendAPIRequest 可能不喜欢被并行调用。

标签: java multithreading algorithm design-patterns java-8


【解决方案1】:

您可以使用并行流。以下调用将并行调用createAPICallDetails(idx),并将其返回对象添加到List

    List<APICallDetails> result = IntStream.range(0, callsCount)
            .parallel()
            .mapToObj(idx -> createAPICallDetails(idx))
            .collect(Collectors.toList());

所以,剩下的唯一事情就是实现以下逻辑:

    APICallDetails createAPICallDetails(int index) { ... }

在给定 index 参数的情况下创建 APICallDetails 的单个对象,以便在之前的 lambda 中使用它。

希望这会有所帮助。

【讨论】:

  • 谢谢,@Macro R.!!我已经尝试通过在我的日志中出现以下错误来在我的代码中实现这一点,并且我的 Web 应用程序在所有页面上都抛出 404 HTTP 状态。严重:向 org.springframework.beans.factory.BeanDefinitionStoreException 类的侦听器实例发送上下文初始化事件的异常:无法读取候选组件类:文件 [C:\Bharat\IDEs\JavaWorkspace\.metadata\.plugins\org.eclipse. wst.server.core\tmp0\wtpwebapps\R6TestKit\WEB-INF\classes\com\capgemini\controller\APICallController.class];嵌套异常是 java.lang.ArrayIndexOutOfBoundsException: 153
  • 我共享的代码有效地并行运行了一个循环。我建议您创建一个包含所有相关详细信息的新问题,因为这个新问题超出了当前问题的范围。
  • 感谢您的回复!!是的,我也同意这是完全不同的事情。但不知何故,上面的代码是导致此错误的唯一原因。当我从我的代码中删除这段代码 sn-p 时,一切都开始工作了。每当我再次添加它时;它会停止网络应用程序的启动。
  • 确保您正确实施APICallDetails createAPICallDetails(int index) { ... }。例如我给你的代码已经创建了List并添加了所有元素,所以不需要apiCallDetailsArray.add(apiCallDetails)或任何列表操作,只需创建对象并返回它。
  • 谢谢马可!!这对我帮助很大。我刚刚将代码从控制器移动到服务类,它开始工作了。
猜你喜欢
  • 2017-09-25
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多