我第一次开始玩Scala Futures。我对非阻塞(即非Await.Result
)解决方案感兴趣,以在运行一些异步数据库查询时保持我的主线程处于活动状态。使用到目前为止在回调中找到的信息,我将类似的内容汇总在一起。
def miniFuturesExample(conn: DatabaseConnection)
{
val f1 = Future { runQuery(conn) }
f1.onComplete
{
case Success(result) => println(result.next())
case Failure(e) => e.printStackTrace()
}
// do some other stuff
Thread.sleep(2000)
}
我希望避免的是为Thread.sleep
指定一个时间值。我不想对此进行硬编码的原因是,因为我并不总是确定runQuery
方法将花费多长时间。我想找到一种非阻塞解决方案来保持主线程保持活动状态,直到触发onComplete
的{{1}}块为止。
答案 0 :(得分:0)
sleep
并没有“不阻塞”的意思:)
如果您希望线程在异步任务完成之前一直处于空闲状态,则必须将其阻塞(这就是阻塞的意思)。 Await.result
正是您想要的。
或者,您可以设置监视器并在其上wait
进行以下操作:
Future { runQuery(conn) }
.onComplete { result =>
result match {
case Success(r) => println(r.next)
case Failure(e) => e.printStackTrace()
}
synchronized { notifyAll }
}
synchronized { wait }
但实际上,它与Await.result
是同一件事,只是比较笨拙。
答案 1 :(得分:0)
import scala.annotation.tailrec
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object WaitFuture {
@tailrec
def checkFutureComplete[T](f: => Future[T]): Unit = {
if(f.isCompleted) ()
else checkFutureComplete(f)
}
def main(args: Array[String]): Unit = {
val k = Future {
Thread.sleep(12000)
println("Coming")
10
}
checkFutureComplete(k)
println(k)
val k2 = k
println(k2)
}
}
//
//Coming
//Future(Success(10))
//Future(Success(10))
未来是非阻塞和异步任务。并且只有当您在它们上Await
时,您才能转换(Future[T] => T)
。正如@Dima所发布的那样,此方法也类似于Await.result,在此我们以递归方式尾部检查future的状态。即使我们进行检查,也永远无法获得T值,但只能在没有Future(Success(T))
的情况下实现Await
。