Scala阻止地图

时间:2017-03-09 05:17:19

标签: java multithreading mongodb scala csv

我在项目中使用Scala,我遇到以下情况:

我正在阅读csv文件,我有以下结构:

mail,file,action
ex1@...,file1,insert
ex2@...,file2,update

我的mongodb中有三个集合:用户,文件,操作和; Actions引用文件和用户ID。

架构将是这样的:

Action {
 actionName: String,
 userId: ObjectId, 
 fileId: ObjectId 
}

问题是我在阅读csv时没有这些ID。它们是在阅读过程中创建的。所以我的主要问题是:如果用户和文件在您尝试使用它们时重新插入,如何引用它们。

我最初的解决方案是创建3个踏板以保存代码的每个部分并使用两个贴图:Map1 [userMail,Ids]和Map2 [fileName,Ids]。在数据库中插入用户或文件后,代码将采用各自的ID并放入地图中。

与此同时,我有一个保存动作的线程。这个线程在它们具有两个id时保持汇集这些映射。只要它有,它就会保存动作(让我们调用它"动作线程")。像这样:

while(filesMap.get(action.fileId) == None) {
  Thread.sleep(1000)
}
while(usersMap.get(action.userId) == None) {
  Thread.sleep(1000)
} ... //save code omitted for clarity

此代码有效,但问题是它太慢了。我相信"动作线程"正在使用其池来锁定映射,从而阻止从实际将数据保存到数据库的线程中进行一些写入。

所以,我的问题是:是否有一种更聪明的方式来通知"动作线程"那些ID在那里并删除了池代码,或者,在 scala 中是否有更好的方法可以开箱即用?

我在Javascript中使用promises和resolve做了类似的事情,但由于我使用Scala工作不到一个月,我不知道如何移植代码。

由于

2 个答案:

答案 0 :(得分:1)

  

如果在您尝试使用这些用户和文件时重新插入这些用户和文件,该如何引用它们

您需要加入。

  

mongodb的

在真实数据库中流式传输所有内容并在那里进行连接。在Scala中完成它基本上是手工重新实现半个数据库...

如果你有无限的内存,你可以在Scala不可变集合中加载所有内容:

val filesMap: Map[Int, File] = ...
val userMap: Map[Int, User] = ...

val actions: Stream[Action] =
  csv.lines.map(csvParser).flatMap { case (actionName, userId, fileId) =>
    for {
      file <- filesMap.get(fileId)
      user <- userMap.get(userId)
    } yield
      Action(actionName, user, file)
  }

答案 1 :(得分:0)

Scala对象不是为多线程访问而设计的。你想在scala中使用actor。

但我想你需要做投票。有可能,只需使用Java

java.util.concurrent.ConcurrentHashMap中 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

Scala适用于Java类。

image