所以我有这段代码
dbs.foreach({
var map = scala.collection.mutable.Map[String, mutable.MutableList[String]]()
db =>
val resultList = getTables(hive, db)
map+=(db -> resultList)
})
此操作是遍历数据库列表,对每个数据库执行show tables in db
调用,然后将db->表添加到映射。由于蜂巢查询需要大约5秒钟的等待时间,该如何同时完成?
更新代码-
def getAllTablesConcurrent(hive: JdbcHive, dbs: mutable.MutableList[String]): Map[String, mutable.MutableList[String]] = {
implicit val context:ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
val futures = dbs.map {
db =>
Future(db, getTables(hive, db))
}
val map = Await.result( Future.sequence(futures), Duration(10, TimeUnit.SECONDS) ).toMap
map
}
答案 0 :(得分:2)
不要使用vars和可变状态,尤其是如果想要并发的话, 。
val result: Future[Map[String, Seq[String]] = Future
.traverse(dbs) { name =>
Future(name -> getTables(hive, name) )
}.map(_.toMap)
答案 1 :(得分:1)
您可以在任何Scala集合上使用.par
来并行执行下一个转换(使用默认并行性,具体取决于内核数)。
而且-更容易和更清洁地将map
映射到(不可变的)映射中,而不是更新可变的映射。
val result = dbs.par.map(db => db -> getTables(hive, db)).toMap
要对使用的并发线程数有更多控制,请参阅https://docs.scala-lang.org/overviews/parallel-collections/configuration.html
答案 2 :(得分:1)
如果您想获得更多控制权(您要等待多少时间,要使用多少个线程,如果所有线程都忙着会发生什么,等等),则可以使用ThreadPollExecutor和Future
implicit val context:ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
val dbs = List("db1", "db2", "db3")
val futures = dbs.map {
name => Future(name, getables(hive, name))
}
val result = Await.result( Future.sequence(futures), Duration(TIMEOUT, TimeUnit.MILLISECONDS) ).toMap
请记住不要在每次需要时都创建一个新的ExecutionContext