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

use*_*911 0 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:关于'docNo'变量的线程安全性的另一个问题.我想将doc序列号传递给Callable.在这种情况下,"docNo"变量的线程安全吗?

Str*_*lok 6

future.get()提交调用后立即调用的事实是使代码有效地单线程化为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());
    }
Run Code Online (Sandbox Code Playgroud)

PS.我想我也会强调在原始问题上提出的IO问题.

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