java - Java的项目中使用scala的ParHashMap代替ConcurrentHashMap

标签 java multithreading scala java.util.concurrent

我有一个相当复杂的项目,它大量使用 Java 的多线程。在回答我之前的一个问题时,我描述了一个丑陋的 hack,它应该克服并行迭代 Java 的 ConcurrentHashMap 的固有缺陷。虽然它有效,但我不喜欢丑陋的黑客,并且在尝试在实际系统中引入建议的概念验证时遇到了很多麻烦。在尝试寻找替代解决方案时,我遇到了 Scala 的 ParHashMap,它声称实现了 foreach 方法,该方法似乎是并行操作的。在我开始学习一门新语言来实现一项功能之前,我想问以下问题:

1) Scala 的 ParHashMapforeach 方法是否可扩展?

2) 从 Scala 调用 Java 代码是否简单直接?反之亦然?我只是提醒一下,代码是并发的并且使用泛型。

3)将部分代码库切换到 Scala 是否会导致性能损失?

作为引用,这是我之前关于 ConcurrentHashMap 并行迭代的问题:

Scalable way to access every element of ConcurrentHashMap<Element, Boolean> exactly once

编辑

我已经用可能非常不惯用的 Scala 实现了概念验证,但它工作得很好。 AFAIK 鉴于其标准库和任何可用的第三方库的当前状态,不可能在 Java 中实现相应的解决方案。

import scala.collection.parallel.mutable.ParHashMap

class Node(value: Int, id: Int){
    var v = value
    var i = id
    override def toString(): String = v toString
}

object testParHashMap{
    def visit(entry: Tuple2[Int, Node]){
        entry._2.v += 1
    }
    def main(args: Array[String]){
        val hm = new ParHashMap[Int, Node]()
        for (i <- 1 to 10){
            var node = new Node(0, i)
            hm.put(node.i, node)
        }

        println("========== BEFORE ==========")
        hm.foreach{println}

        hm.foreach{visit}

        println("========== AFTER ==========")
        hm.foreach{println}

    }
}

最佳答案

我对此提出一些警告:

  • 虽然我可以做一些事情,但我认为自己对 Scala 还比较陌生。
  • 我只读过但从未使用过描述的 par 内容 here
  • 我从未尝试过实现您想要实现的目标。

如果您仍然关心我要说的话,请继续阅读。

首先,这是一个学术paper描述并行集合如何工作。

回答你的问题。

1) 在多线程方面,Scala 比 Java 更轻松。这些抽象真是太棒了。从 par 调用获得的 ParHashMap 会将工作分配给多个线程。如果没有更好地了解您的机器、配置和用例,我无法说明这将如何为您扩展,但如果做得正确(特别是在副作用方面),它将至少与 Java 实现一样好。但是,您可能还想查看 Akka对一切有更多的控制权。听起来这可能比简单的 ParHashMap 更适合您的用例。

2) 使用 JavaConverters 以及 asJavaasScala 方法在 Java 和 Scala 集合之间进行转换通常很简单。我建议确保您的方法调用的公共(public) API“看起来像 Java”,因为 Java 是最不常见的标准。此外,在这种情况下,Scala 是一个实现细节,无论如何你都不想泄露这些细节。因此,请将抽象保持在 Java 级别。

3) 我猜想 Scala 在运行时实际上会带来性能提升。但是,您会发现编译时间要慢得多(可以解决。ish)。此堆栈溢出post Scala 作者的著作很老,但仍然有意义。

希望有帮助。这是一个很大的问题。

关于java - Java的项目中使用scala的ParHashMap代替ConcurrentHashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20164690/

相关文章:

java - 为了获得最大性能,线程池的大小应该是多少?

java - java中如何启动ThreadGroup?

java - 特殊字符使我的程序崩溃?

java - Eclipse Plugin IDE 在处理过程中卡住/不刷新

scala - 如何在 Play 2 中设置选项值以形成映射?

java - Scala/Java 枚举

Scala:在依赖于路径的上下文中重用由依赖于路径的类型产生的泛型

Web 应用程序中的 Java Spring 错误处理性能

java - 如何在 Java 中将 GUI 文件作为另一个类的线程来运行?

java - 无法在新线程中从 FREContext 调用 getActivity()?