使用scala';Java中的s ParHashMap';s项目而不是ConcurrentHashMap

使用scala';Java中的s ParHashMap';s项目而不是ConcurrentHashMap,java,multithreading,scala,java.util.concurrent,Java,Multithreading,Scala,Java.util.concurrent,我有一个相当复杂的项目,它大量使用Java的多线程。在对我前面的一个问题的回答中,我描述了一个丑陋的hack,它被认为是为了克服并行迭代Java的ConcurrentHashMap的固有能力。虽然它可以工作,但我不喜欢丑陋的黑客,而且我在尝试在实际系统中引入建议的概念验证时遇到了很多麻烦。在寻找替代解决方案时,我遇到了Scala的ParHashMap,它声称实现了一个foreach方法,该方法似乎是并行运行的。在我开始学习一种新语言来实现单个功能之前,我想问以下问题: 1) Scala的ParH

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

1) Scala的
ParHashMap的
foreach
方法是否可伸缩

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

3) 将代码库的一部分切换到Scala会有性能损失吗

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

编辑

我已经用非常不惯用的Scala实现了概念验证,但效果很好。考虑到Java标准库和任何可用的第三方库的当前状态,不可能用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.collection.parallel.mutable.ParHashMap
类节点(值:Int,id:Int){
var v=价值
变量i=id
重写def toString():String=v toString
}
对象testParHashMap{
def访问(条目:Tuple2[Int,Node]){
条目。\u 2.v+=1
}
def main(参数:数组[字符串]){
val hm=new ParHashMap[Int,Node]()

对于(i我在这里提出了一些警告:

    虽然我能做一些事情,但我认为自己对斯卡拉来说是比较新的。
  • 我只读过,但从未使用过所描述的
    par
    内容
  • 我从来没有尝试过去完成你想要完成的事情
如果你仍然关心我要说的话,请继续读下去

首先,这里有一篇学术文章描述了平行收集是如何工作的

请回答你的问题

(一)说到多线程,Scala让生活比Java简单得多。抽象非常棒。从
par
调用中获得的
ParHashMap
将把工作分配给多个线程。如果不更好地理解您的机器、配置和用例,我无法说这将如何扩展,但已经完成了是的(特别是在副作用方面),它至少和Java实现一样好。不过,您可能还想看看如何更好地控制一切。这听起来可能比简单地
ParHashMap
更适合您的用例

2) 使用
JavaConverters
asJava
asScala
方法在Java和Scala集合之间进行转换通常很简单。不过我建议确保方法调用的公共API“看起来像Java”因为Java是最小的公分母。此外,在这个场景中,Scala是一个实现细节,你永远不想泄露这些细节。所以将抽象保持在Java级别

3) 我想Scala实际上会在运行时提高性能。但是,您会发现编译时间要慢得多(可以在.ish附近工作)。Scala作者的这个堆栈溢出很老,但仍然相关


希望这会有帮助。这是您遇到的一个相当大的问题。

我在这里提出一些警告:

    虽然我能做一些事情,但我认为自己对斯卡拉来说是比较新的。
  • 我只读过,但从未使用过所描述的
    par
    内容
  • 我从来没有尝试过去完成你想要完成的事情
如果你仍然关心我要说的话,请继续读下去

首先,这里有一篇学术文章描述了平行收集是如何工作的

请回答你的问题

1) 说到多线程,Scala让生活比Java简单得多。抽象非常棒。从
par
调用中获得的
ParHashMap
将把工作分配给多个线程。如果不更好地理解您的机器、配置和用例,我无法说这将如何扩展,但是做对了(特别是在副作用方面),它至少会和Java实现一样好。不过,您可能还想看看如何更好地控制一切。这听起来可能比简单地
ParHashMap
更适合您的用例

2) 使用
JavaConverters
asJava
asScala
方法在Java和Scala集合之间进行转换通常很简单。不过我建议确保方法调用的公共API“看起来像Java”因为Java是最小的公分母。此外,在这个场景中,Scala是一个实现细节,你永远不想泄露这些细节。所以将抽象保持在Java级别

3) 我想Scala实际上会在运行时提高性能。但是,您会发现编译时间要慢得多(可以在.ish附近工作)。Scala作者的这个堆栈溢出很老,但仍然相关


希望这会有帮助。这是一个相当大的问题。

因为Scala编译成与Java相同的字节码,所以无论任务如何,在两种语言中使用相同的字节码都是非常有可能的。然而,有些事情在Scala中更容易解决,但如果这值得学习,一种新的语言是另一个问题。特别是在Java之后8将包括您要求的内容:简单并行执行列表上的函数。

final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); //... final Entry<String, String>[] elements = (Entry<String, String>[]) myMap.entrySet().toArray(); final AtomicInteger index = new AtomicInteger(elements.length); for (int i = Runtime.getRuntime().availableProcessors(); i > 0; --i) { executor.submit(new Runnable() { public void run() { int myIndex; while ((myIndex = index.decrementAndGet()) >= 0) { process(elements[myIndex]); } } }); }