2016-07-26 125 views
0

我有一个循环的函数,我打算并行但不知道多线程的负载是否会超过并发的好处。将一个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?

回答

1

所有我需要的是不同的日志文件发送到相应的接收器。目前我们可以说接收器的数量不会超过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(...)

更多实施细节从这good ExecutorService tutorial

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

+0

谢谢你这么多。我在不同的机器上有日志文件和接收器,所以在这种情况下,我会达到你提到的另一种情况的性能吗? – aneela

+0

如果您有多台不同的机器,则将日志文件发送到不同的机器可能确实会提高性能。很难真正知道没有更多细节@aneela。 – Gray

2

Hello ExecutorService当然是一个选项。你有4种方法可以在Java中完成。

  1. 使用线程(暴露到很多细节容易出错)
  2. 执行人的服务为您已经提到。它来自Java 6的 这里是一个教程演示的ExecutorService http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
  3. ForkJoin框架来自于爪哇7
  4. ParallelStreams来自于爪哇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();}) 
+0

谢谢这么多,但不幸的是我没有java 8.如果它不是一个负担,你可以给我一个解决方案在6或7,我可以更好地理解? – aneela