简体   繁体   English

用于java.util.concurrent.Future的scala.concurrent.Future包装器

[英]scala.concurrent.Future wrapper for java.util.concurrent.Future

I'm using Play Framework 2.1.1 with an external java library that produces a java.util.concurrent.Future result. 我正在使用Play Framework 2.1.1和一个生成java.util.concurrent.Future结果的外部Java库。 I'm using the scala future's as opposed to Akka which I think is the right thing to do as of Play 2.1. 我正在使用scala future而不是Akka,我认为这是Play 2.1的正确选择。 How can I wrap the java.util.concurrent.Future up into a scala.concurrent.Future while still keeping the code non-blocking? 如何在保持代码无阻塞的同时将java.util.concurrent.Future包装到scala.concurrent.Future中?

def geConnection() : Connection = {
  // blocking with get
  connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}

The above code returns a connection but uses a get so it becomes blocking 上面的代码返回一个连接,但使用了get,所以它变成了阻塞

def getConnectionFuture() : Future[Connection] = {
  future {
    // how to remove blocking get and return a scala future?
    connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
  }
}

Ideally I want a scala function that returns the connection as a future like the code above but without the code blocking via the get. 理想情况下,我想要一个scala函数,它返回连接作为未来,如上面的代码,但没有通过get阻止代码。 What else do I need to put into the function to make it non blocking. 我需要在函数中添加什么才能使其无阻塞。

Any pointers would be great. 任何指针都会很棒。

import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}

You can't wrap JFuture with SFuture without blocking since there is a callback in SFuture ( onComplete ) and there is only blocking get in JFuture . 你不能在没有阻塞的情况下用SFuture包装JFuture ,因为在SFuture有一个回调( onComplete )并且在JFuture只有阻塞get

All you can do is to create additional thread and block it with get , then complete Promise with result of get . 所有你能做的是创造更多的线程,并阻止它get ,然后完成Promise与结果get

val jfuture: JFuture[T] = ???
val promise = Promise[T]()
new Thread(new Runnable { def run() { promise.complete(Try{ jfuture.get }) }}).start
val future = promise.future

You could check isDone in endless loop, but I don't think it is better then blocking. 你可以在无限循环中检查isDone ,但我不认为它比阻塞更好。

Future {
  blocking {
    jfuture.get
  }
}

This lets the ExecutionContext know that what you are doing is going to block, giving it a chance to allocate more threads. 这使得ExecutionContext知道你正在做的事情将会阻塞,让它有机会分配更多的线程。 If you do not include blocking { } then you may run out of threads. 如果您不包含blocking { }那么您可能会用尽线程。

     import java.util.concurrent.{Future => JFuture}
     import scala.concurrent.ExecutionContext.Implicits.global
     import scala.concurrent.Future
     import scala.util.Try

     object JFuture2SFuture {
        val jFuture: JFuture[Int] = ???
        val promise = Promise[Int]()
        Future { promise.complete(Try(jFuture.get)) } //it is non blocking 
        val sFuture:Future[Int] = promise.future

     }

The scala-java8-compat library provides converters between java8 and Scala Futures. scala-java8-compat库提供java8和Scala Futures之间的转换器。

Specifically, you can use FutureConverters.toScala(connectionPool.getConnectionAsync()) to convert the java.util.concurrent.Future to scala.concurrent.Future 具体来说,您可以使用FutureConverters.toScala(connectionPool.getConnectionAsync())java.util.concurrent.Future转换为scala.concurrent.Future

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM