【问题标题】:How to use multi-threading to make my application faster如何使用多线程让我的应用程序更快
【发布时间】:2018-02-24 20:43:12
【问题描述】:

我正在遍历一个包含 +- 1500 个条目的字符串列表。在每次迭代中,我再次遍历字符串列表,但这次有 +- 3500 万个条目。应用的结果是完美的。但是应用程序需要很长时间(2 多个小时)才能给我结果。我应该如何构建多线程以使我的应用程序更快?

结果列表的顺序并不重要。

  • 我是否应该将大列表(3500 万个条目)划分为更小的块并通过它们并行迭代? (如何确定完美的块数?)
  • 我应该为小列表中的每个迭代启动一个线程吗? (这将创建 1500 个线程,我猜其中很多会“并行”运行)

我还有哪些其他选择?

代码表示:

List<String> result = new ArrayList<String>();
for(Iterator<String> i = data1.iterator();i.hasNext();){ //1500 entries
  String val = i.next();
  for(Iterator<String> j = data2.iterator();j.hasNext();){ //35 million entries
    String test = j.next();
    if(val.equals(test)){
      result.add(val);
      break;
    }
  }
}
for(Iterator<String> h = result.iterator();h.hasNext();){
  //write to file
}

更新

在重构我的代码并实现 JB Nizet 给出的答案后,我的应用程序现在运行得更快了。现在只需 20 秒即可获得相同的结果!没有多线程!

【问题讨论】:

  • 1500 条记录的哈希集...所以循环是 O(1)?
  • 如何使用比列表更高效的东西,比如 HashSet 并在上面调用contains
  • 使用并行流
  • 好吧,如果你启动 1k5 个线程,除非你有 1k5 个内核,否则它们中的很多会争抢资源,而且我认为它不会像你想象的那么快。
  • 您的代码与您的描述不符。第二个数据来自哪里。每个val都一样吗?每个 val 的列表是否不同?

标签: java multithreading list concurrency hashset


【解决方案1】:

您可以使用并行流:

List<String> result = 
    data1.parallelStream()
         .filter(data2::contains)
         .collect(Collectors.toList());

但是由于您在 data2 上调用 contains() 1500 次,并且由于 contains() 对于列表来说是 O(N),因此首先将其转换为 HashSet 可以使事情变得更快:HashSet 上的 contains() 是 O (1)。您甚至可能不再需要多线程:

Set<String> data2Set = new HashSet<>(data2);
List<String> result = 
    data.stream()
        .filter(data2Set::contains)
        .collect(Collectors.toList());

【讨论】:

  • 我猜想将 List data2 转换为 HashSet?
  • 好吧,我的回答是怎么说的? Set&lt;String&gt; data2Set = new HashSet&lt;&gt;(data2);.
  • 我假设这仅在列表和哈希集中的字符串是相同对象时才有效?还是比较字符串的值?因为在这种情况下data1和data2中的对象是不一样的(值是从不同的csv文件中读取的)
  • 当然不是。 HashSet.contains() 和 List.contains() 都通过调用 equals() 来比较对象。如果两个字符串以相同的顺序包含相同的字符,则它们是相等的。 docs.oracle.com/javase/7/docs/api/java/util/…
  • 感谢您的清晰解释。对你来说显而易见的事情对每个人来说并不明显;-)
【解决方案2】:

我也同意你的想法。你现在需要做什么?

  1. 首先计算系统中的处理器数量。
  2. 根据处理器数量拆分您的记录并准确创建该数量的线程。 (numberofprocessor * 2 max,否则会因为线程间的上下文切换而降低性能)。

不要创建不必要的大量线程。这不会加速您的应用程序。根据系统中的处理器数量和内存大小,准确检查应该创建多少线程。高效的并行处理也取决于您的机器硬件。

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 2016-10-19
    • 2011-02-13
    • 2014-02-27
    • 1970-01-01
    相关资源
    最近更新 更多