当前位置: 首页 > 知识库问答 >
问题:

简单的多线程Java app-ExecutorService?分叉/连接?分离器?

锺高翰
2023-03-14

我正在用Java 8编写一个命令行应用程序。有一部分涉及一些计算,我相信使用多个线程并行运行可能会带来好处。然而,我在编写多线程应用程序方面没有太多经验,因此我希望您能引导我朝着正确的方向前进,我应该如何设计代码的并行部分。

为了简单起见,让我们假设所讨论的方法接收到一个相对较大的长数组,它应该返回一个只包含素数的集:

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;
}

现在,我想重构方法提取PrimeNumbers(),使其由四个线程并行执行,当所有线程都完成时,返回结果。在我的脑海中,我有以下问题:

  • 哪种方法更适合该任务:ExecutorService还是Fork/Join?(inputArray[]的每个元素都是完全独立的,它们可以以任何顺序处理)
  • 假设inputArray[]中有100万元素,我应该“要求”线程#1处理所有索引0...249999、线程#2 - 250000..499999、线程#3 - 500000..749999和线程#4 - 750000..999999吗?或者我应该将inputArray[]的每个元素视为一个单独的任务来排队,然后由适用的工作线程执行?
  • 如果检测到素数,则应将其添加到“设置结果”中,因此它需要是线程安全的(同步的)。所以,也许最好每个线程都保持自己的本地结果集,并且只有在它完成时,它才会将其内容一次性传输到全局结果?
  • Spliterator在这里有任何用处吗?它们应该用于以某种方式对inputArray[]进行分区吗?

共有1个答案

魏翔
2023-03-14

不要使用这些。并行流将足以比您列出的任何备选方案更直接地处理这个问题。

return Arrays.parallelStream(inputArray)
  .filter(n -> checkIfNumberIsPrime(n))
  .boxed()
  .collect(Collectors.toSet());
 类似资料:
  • 我不确定的是,在这种情况下,会创建多少个线程?我在一台2核心的机器上运行,所以每核心24个线程,最多48个线程? 当并行度因子设置为4.0时,可以并行运行的线程数将是8。那么,设置最小值和最大值(我的例子是24和48)的需要是什么?

  • 问题内容: 我一直在使用库在C中创建和加入线程。 什么时候应该从一开始就创建分离的线程?与可连接线程相比,它具有任何性能优势吗? 不在可连接(默认)线程上执行合法操作吗?还是这样的线程应该在使用之前始终使用该函数? 问题答案: 当您知道不想等待时,创建一个分离线程。唯一的性能好处是,当分离的线程终止时,可以立即释放其资源,而不必等到线程加入后才可以释放资源。 不加入可连接的线程是“合法的”。但是通

  • 我想知道是否有任何方法可以在GitHub中重新附加一个“分离”的存储库? 事件顺序: 从我所属的组织中派生出一个私有存储库 父级、私有存储库已公开 我还公开了我的分叉存储库(或收取账单) 现在,当我希望提交pull请求并合并一些更改时,我注意到我的fork与父存储库“分离”(请参阅此解释和确认,了解原因) 有没有希望“重新连接”这把叉子?或者我应该重命名我的存储库,再次分叉,然后复制代码? 欢迎提

  • 问题内容: 我以前在应用程序中使用过线程,并且对线程的概念非常了解,但是最近在我的操作系统讲座中,我遇到了fork()。这类似于线程。 我用谷歌搜索了它们之间的区别,我知道: Fork只是一个看起来与旧流程或父流程完全相似的新流程,但它仍然是具有不同流程ID并拥有自己内存的不同流程。 线程是轻量级进程,具有较少的开销 但是,我仍然有一些疑问。 什么时候应该更喜欢fork()而不是线程? 如果我想以

  • 我有一个任务来创建一个独立的java应用程序来做以下事情: 解析一个。csv文件。(这将有大约300万条记录) 对于每条记录,在几个DB表中插入约15行 如果出现错误,则输出。csv记录是否已成功处理 我目前的设计思路是: 读这本书。csv文件(这一步还没有考虑太多) 每个线程都有逻辑: 创建数据库连接

  • 情况是应用程序不时地无限挂起。 执行代码的线程在上冻结: 可以假设传递给的任务执行时间过长。 但令人惊讶的是,线程转储中没有出现,因此看起来池没有执行任何计算!