Scala Futures-在不显式设置时间延迟的情况下使主线程保持活动状态

时间:2018-07-19 16:47:36

标签: scala

我第一次开始玩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}}块为止。

2 个答案:

答案 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