简体   繁体   English

简单的多线程 Java 应用程序 - ExecutorService? 分叉/加入? 分离器?

[英]Simple multi-threaded Java app - ExecutorService? Fork/Join? Spliterators?

I am writing a command-line application in Java 8. There's a part that involves some computation, and I believe it could benefit from running in parallel using multiple threads.我正在用 Java 8 编写一个命令行应用程序。有一部分涉及一些计算,我相信它可以从使用多个线程并行运行中受益。 However, I have not much experience in writing multi-threaded applications, so I hope you could steer me in the right direction how should I design the parallel part of my code.但是,我在编写多线程应用程序方面没有太多经验,所以我希望你能引导我朝着正确的方向前进,我应该如何设计我的代码的并行部分。

For simplicity, let's pretend the method in question receives a relatively big array of longs, and it should return a Set containing only prime numbers:为简单起见,让我们假设有问题的方法接收到一个相对较大的 long 数组,它应该返回一个仅包含素数的 Set:

public final static boolean checkIfNumberIsPrime(long number) {
  // algorithm implementation, not important here
  // ...
}

// a single-threaded version
public Set<Long> extractPrimeNumbers(long[] inputArray) {
  Set<Long> result = new HashSet<>();
  for (long number : inputArray) {
    if (checkIfNumberIsPrime(number)) {
      result.add(number);
    }
  }
  return result;
}

Now, I would like to refactor method extractPrimeNumbers() in such way that it would be executed by four threads in parallel, and when all of them are finished, return the result.现在,我想重构方法extractPrimeNumbers() ,使其由四个线程并行执行,当所有线程都完成后,返回结果。 Off the top of my head, I have the following questions:在我的脑海中,我有以下问题:

  • Which approach would be more suitable for the task: ExecutorService or Fork/Join?哪种方法更适合该任务: ExecutorService还是 Fork/Join? (each element of inputArray[] is completely independent and they can be processed in any order whatsoever) inputArray[]的每个元素都是完全独立的,它们可以按任何顺序处理)
  • Assuming there are 1 million elements in inputArray[] , should I "ask" thread #1 to process all indexes 0..249999, thread #2 - 250000..499999, thread #3 - 500000..749999 and thread #4 - 750000..999999?假设inputArray[]中有 100 万个元素,我是否应该“要求”线程 #1 处理所有索引 0..249999、线程 #2 - 250000..499999、线程 #3 - 500000..749999 和线程 #4 - 750000..999999? Or should I rather treat each element of inputArray[] as a separate task to be queued and then executed by an applicable worker thread?还是我应该将inputArray[]的每个元素视为一个单独的任务,然后排队并由适用的工作线程执行?
  • If a prime number is detected, it should be added to `Set result, therefore it needs to be thread-safe (synchronized).如果检测到素数,则应将其添加到 `Set 结果中,因此它需要是线程安全的(同步的)。 So, perhaps it would be better if each thread maintained its own, local result-set, and only when it is finished, it would transfer its contents to the global result, in one go?那么,如果每个线程都维护自己的本地结果集,并且只有当它完成时,它会一次性将其内容传输到全局结果中,也许会更好?
  • Is Spliterator of any use here? Spliterator在这里有用吗? Should they be used to partition inputArray[] somehow?它们是否应该用于以某种方式对inputArray[]进行分区?

Use none of these.不使用这些。 Parallel streams are going to be enough to deal with this problem much more straightforwardly than any of the alternatives you list.与您列出的任何替代方案相比,并行流足以更直接地处理这个问题。

return Arrays.parallelStream(inputArray)
  .filter(n -> checkIfNumberIsPrime(n))
  .boxed()
  .collect(Collectors.toSet());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM