使用scala';Java中的s ParHashMap';s项目而不是ConcurrentHashMap
我有一个相当复杂的项目,它大量使用Java的多线程。在对我前面的一个问题的回答中,我描述了一个丑陋的hack,它被认为是为了克服并行迭代Java的使用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
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]);
}
}
});
}