【问题标题】:FixedThreadPool threadcount and runtimeFixedThreadPool 线程数和运行时
【发布时间】:2017-05-24 13:11:44
【问题描述】:

我编写了一个简单的工具,它检查一些 xml(解组和内容分析)的内容并为每个 xml 编写一个日志文件。

我必须检查大约 2 MB / 文件的一千多个文件。所以进步需要一些时间。因为我的文件之间没有依赖关系,所以我尝试在不同的线程中完成工作(没有同步方法)。

不幸的是,我的 ExecutorService 似乎有问题。我尝试使用固定线程池 Executorservice。但是具有 1 个和 100 个线程的运行时几乎不一样(以及 cpu 使用率)。只有当我每个文件使用 1 个线程(files.size)时,cpu 使用率才会高得多(大约 90%),并且运行时大约是原始运行时的 10%。

我不明白为什么 1 个线程的运行时和 cpu 使用率与 100 个线程相同。

package mycode;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Starter {

public static void main(String[] args) {
    File config = new File(args[0]);
    Starter starter = new Starter(); 
    starter.work(config);
}

private void work(File config)
{
    Long start = System.currentTimeMillis();
    ConfigReader cr = new ConfigReader(config);
    cr.init();
    FileFinder ff = new FileFinder();
    List<File>files = ff.findfiles(cr.getParam("xmlfolder"));
    List<String>done = new ArrayList<String>();


    ExecutorService es = Executors.newFixedThreadPool(Integer.parseInt(cr.getParam("max.threadcount")));
    for (File aktuell : files)
    {
        es.execute(new Threadstarter(aktuell, cr.getParam("logoutput"), done)); 
    }



    es.shutdown();


    try {
        es.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Long end = System.currentTimeMillis(); 
    BufferedWriter logwriter; 
    try {
        logwriter = new BufferedWriter(new FileWriter(new File(cr.getParam("logoutput")).getAbsolutePath()+"/log.log"));
        for (String temp : done)
        {
            logwriter.write(temp);
            logwriter.newLine();
        }
        logwriter.write("Die Verarbeitung dauerte "+(end-start)/1000 +" Sekunden");
        logwriter.newLine();
        logwriter.write("Es wurden "+files.size()+" Dienststellen verarbeitet");
        logwriter.flush();
        logwriter.close();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


}

}

【问题讨论】:

  • 当您将max.threadcount 指定为 1 和将其指定为 100 时,您无法找到差异?您能否提供一个最小的可重现代码,因为查看此代码我认为您应该获得 X 个并行处理线程,其中 X = max.threadcount
  • 当你只用一个线程运行时,进程花费多少时间进行计算,花费多少时间进行I/O?您的计算机可能有多个 CPU,因此添加更多线程可以使其计算速度更快(最多可达到您拥有的 CPU 数量),但如果所有这些文件都在同一个磁盘上......只有一个端口用于与磁盘交谈。添加更多线程根本不会改善 I/O 时间。

标签: java multithreading executorservice


【解决方案1】:

我认为没有关系或不容易。这取决于线程正在执行的工作。具有一个线程的程序可以消耗 100% 的 CPU,而具有大量线程的程序可以消耗更少的 CPU。

如果您正在寻找线程和已完成工作之间的优化关系,您必须研究您的案例,并可能找到经验解决方案。

【讨论】:

    【解决方案2】:

    感谢您的回复。

    正如@hagrawal 所写,使用 1、10 或 100 个线程没有区别。只要我使用与列表中的文件一样多的线程,我就有更多的 CPU 使用率(直到 CPU 成为瓶颈),整个进度需要大约 10% 的时间。不幸的是,这需要大量内存,而且我担心将来会导致软件崩溃,文件更多。

    我无法想象,这可能是 I/O 问题。我机器的raid 0系统应该可以毫不费力地做到这一点。如果我对问题的理解是正确的,那不可能是 I/O 问题。因为如果 I/O 是瓶颈,那么如果线程数等于文件数(在我的情况下约为 1000),性能应该不会提高。还是我的造币厂有问题?

    不幸的是,CPU 使用率与 1、10 和 100 个线程几乎不完全相同。所以我的印象是,进程从固定数量的线程(如配置)开始,执行程序服务等待所有线程终止,然后再启动一个新线程。但我的理解是,一旦第一个线程终止并释放,它就会启动一个新线程?

    【讨论】:

      猜你喜欢
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 2014-08-07
      • 2019-06-03
      • 1970-01-01
      相关资源
      最近更新 更多