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

标签 java multithreading java.util.concurrent

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

问题是,当设置“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;
}

编辑:关于“docNo”变量的线程安全性的另一个问题。我想将文档序列号传递给 Callable。在这种情况下,“docNo”变量是线程安全的吗?

最佳答案

事实上,您在提交可调用对象后立即调用 future.get() ,这使得您的代码有效地单线程为 get block ,并且您没有提交在未来得到解决的同时,还有更多的任务要添加到池中。在一个循环中提交所有内容并存储 future。然后迭代 future 列表以收集结果。

这样更好:

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. 我想我也会强调 commeters 在原始问题上提出的 IO 问题。

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

关于java - 我的多线程代码运行速度并不快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44733366/

相关文章:

java - 如何检查Tomcat Web应用程序是否正在运行,如果有错误则重定向到另一台服务器?

python - 在 QLabel 中显示相机流

Java ReentrantReadWriteLock - 正确用法?

java - Log4j 2 : can't use the ContextMapLookup in RollingFileAppender fileName and filePattern

java - 在另一个屏幕元素上设置 ARCore Sceneview

java - 使用不同的 SQL 语句进行PreparedStatement批处理

python - 同时训练两个模型

.net - Thread.Abort() 函数在 Mono 框架中不起作用

非多线程程序中的java.util.ConcurrentModificationException

java - 创建自定义 java.util.concurrent.ForkJoinTask<V>