簡體   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