我的多线程代码运行速度不快

时间:2017-06-24 06:05:33

标签: java multithreading java.util.concurrent

我的电脑有8个内核和64G内存。我的使用多线程的方式如下吗?它处理来自每个文档的一行(filePath)并将结果存储到Document列表中,最后返回。

问题是,当#4;' 4' 4时,我没有看到它运行得更快。线程设置。花在测试数据上的时间总是与单线程运行所需的时间相同。我使用Callable的方式有什么问题吗?

  List<Document> processDocs(String filePath)  {          
          ExecutorService pool = Executors.newFixedThreadPool(4);
          List<Document> processedDocs = new ArrayList<>();
            try {
                br = new BufferedReader(IOUtils.fileReader(filePath));

                String line = null;
                int docNo=0;
                while ((line = br.readLine()) != null) {
                    line = line.trim();

                    Callable<Document> callable = new NLPTextThread(line, ++docNo);
                    Future<Document> future = pool.submit(callable);
                    try {
                        processedDocs.add(future.get());
                    } catch (InterruptedException e) {
                        log.error("InterruptedException " + line);
                    } catch (ExecutionException e) {
                        log.error("ExecutionException: " + line);
                        e.printStackTrace();
                    }
                }
                pool.shutdown();

   return processedDocs;
}

编辑:关于&#39; docNo&#39;的线程安全性的另一个问题。变量。我想将doc序列号传递给Callable。在这种情况下,它是否适用于&#34; docNo&#34;变量?

2 个答案:

答案 0 :(得分:6)

您在提交callable后立即调用get这一事实使您的代码有效地作为List<Document> processDocs(String filePath) { List<Callable<Document>> tasks = new ArrayList<>(); try { BufferedReader br = new BufferedReader(IOUtils.fileReader(filePath)); String line = null; while ((line = br.readLine()) != null) { tasks.add(new NLPTextThread(line.trim()); } ExecutorService executor = Executors.newfixedThreadPool(4); return executor.invokeAll(tasks) .stream() .map(future -> { try { return future.get(); } catch (Exception e) { throw new IllegalStateException(e); } }).collect(Collectors.toList()); } 块进行单线程处理,并且在未来解决时您不再向池中提交任何任务。在一个循环中提交所有内容并存储期货。然后迭代期货清单以收集结果。

这样更好:

PS.

NLPTextThread我以为我也会突出显示原始问题上提出的IO问题。

如果每行文件的to执行时间可以忽略不计(与从文件中读取此行所需的时间相比),我认为您不会看到重要使用线程池改进运行时作为IO在这种情况下实际上是一个瓶颈,因为您正在主线程上读取单个大文件(单线程)。如果将输入(如果它很大)分成多个文件并并行处理每个文件,您可能会看到性能提升。只是一些值得思考的东西。

答案 1 :(得分:2)

futures.add(future);
...
// while loop exits
for (Future<Document> future : futures) {
    try {
        processedDocs.add(future.get());
    } catch (InterruptedException e) {
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

该行等待工作人员在从文件中读取另一行之前完成作业。您应该将期货保存到列表中,然后在读取完毕后将其全部保存。

更像是

swrevealviewcontrtoller