繁体   English   中英

将for循环转换为多线程块

[英]Convert a for loop to a Multi-threaded chunk

我打算在函数中进行并行处理的下一个for循环部分,但不确定多个线程的负载是否会增加并发的好处。

我需要的是将不同的日志文件发送到相应的接收者。 就目前而言,可以说接收器的数量不会超过10。如果不将记录文件背靠背发送,那么将它们全部并行发送会更有效吗?

for(int i=0; i < receiversList.size(); i++)
        {
            String receiverURL = serverURL + receiversList.get(i);
            HttpPost method = new HttpPost(receiverURL);

            String logPath = logFilesPath + logFilesList.get(i);
            messagesList = readMsg(logPath);

            for (String message : messagesList) {
                StringEntity entity = new StringEntity(message);
                log.info("Sending message:");
                log.info(message + "\n");
                method.setEntity(entity);
                if (receiverURL.startsWith("https")) {
                    processAuthentication(method, username, password);
                }
                httpClient.execute(method).getEntity().getContent().close();
            }
            Thread.sleep(500); // Waiting time for the message to be sent
        }

还请告诉我,如果它可以正常工作,该如何使其平行? 我应该手动还是使用ExecutorService?

Hello ExecutorService当然是一个选择。 您有4种使用Java的方法。

  1. 使用线程(暴露于很多细节容易出错)
  2. 您已经提到过执行器服务。 它来自Java6。这是一个演示ExecutorService的教程,网址为http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
  3. ForkJoin框架来自Java 7
  4. ParallelStreams来自Java 8,以下是使用ParallelStreams的解决方案

选择更高级别的api将为您节省一些您可能会遇到的错误。

receiversList.paralelstream().map(t->{
                                      String receiverURL = serverURL + receiversList.get(i);
                                      HttpPost method = new HttpPost(receiverURL);

                                             String logPath = logFilesPath + logFilesList.get(i);
                                             return readMsg(logPath);
                                             })
                                     .flatMap(t->t.stream)
                                     .forEach(t->{
        StringEntity entity = new StringEntity(message);
                        log.info("Sending message:");
                        log.info(message + "\n");
                        method.setEntity(entity);
                        if (receiverURL.startsWith("https")) {
                            processAuthentication(method, username, password);
                        }
                        httpClient.execute(method).getEntity().getContent().close();})

我需要的是将不同的日志文件发送到相应的接收者。 暂时说接收者的数量不会超过10。如果不将记录文件背靠背发送,那么将它们全部并行发送会更有效吗?

在确定并行执行是否可以为您带来任何好处之前,还有很多问题要问。 您提到了“接收方”,但您是在说不同网址上的不同接收服务器,还是所有线程都将其日志文件发送到同一服务器? 如果是后者,那么并发的速度几乎没有改善。 一个线程应该能够很好地填充网络管道。

另外,如果消息很小,您可能不会加快速度。 如果同时发送大型消息,那么它们将花费任何时间,并为您带来真正的节省。

我最熟悉ExecutorService类。 您可以执行以下操作:

ExecutorService threadPool = Executors.newFixedThreadPool(10);
...
threadPool.submit(new Runnable() {
    // you could create your own Runnable class if each one needs its own httpClient
    public void run() {
          StringEntity entity = new StringEntity(message);
          ...
          // we assume that the client is some sort of pooling client
          httpClient.execute(method).getEntity().getContent().close();
      }
    }
});

如果您想将这些消息排队,并在后台线程中发送它们,以免降低程序速度,那是很好的。 然后,您可以将消息提交到threadPool并继续前进。 或者,您可以将它们放在BlockingQueue<String>并让一个线程从BlockingQueue取出并调用httpClient.execute(...)

良好的ExecutorService教程提供了更多实施细节。

最后,如何将所有消息放入一个实体并在服务器上划分消息。 尽管您可能无法控制服务器处理程序代码,但这将是最有效的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM