scala.concurrent.Future wrapper for java.util.concurrent.Future
Solution 1
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
.
All you can do is to create additional thread and block it with get
, then complete Promise
with result of 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.
Solution 2
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. If you do not include blocking { }
then you may run out of threads.
Solution 3
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
}
Related videos on Youtube
Mark Sivill
Updated on December 04, 2020Comments
-
Mark Sivill over 3 years
I'm using Play Framework 2.1.1 with an external java library that produces a java.util.concurrent.Future result. 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. How can I wrap the java.util.concurrent.Future up into a scala.concurrent.Future while still keeping the code non-blocking?
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
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. What else do I need to put into the function to make it non blocking.
Any pointers would be great.
-
Randall Schulz almost 11 yearsWhich version of Scala are you using? As of 2.10.x, Scala adopted Akka's Future as its own.
-
Mark Sivill almost 11 yearsPlay 2.1.1 uses Scala 2.10.0 under the covers
-
-
cmbaxter almost 11 yearsAgreed. Total shame that the Java future does not support some sort of completion listener/observer for a callback
-
fge almost 11 years@cmbaxter if you use Guava, there is
ListenableFuture
-
Mark Sivill almost 11 yearsSo I was thinking along the lines of a callback for the java peice, that when finished, would have its result up in scala future. Looking around there are examples of callbacks implemented in Java (technology.amis.nl/2009/02/19/…) but wasn't sure how to roll this into Play 2.1. Optimistically I was hoping for a simple wrapper but it doesn't look thats doable, and a java callback within a scala function looks the way to go.
-
Petr almost 11 yearsI'm curious, what's wrong with
future { jfuture.get }
? Why you used an extra thread combined withPromise
? -
senia almost 11 years@PetrPudlák: it'll block thread in your thread pull. If you have a configured
ExecutionContext
for such futures it's fine, but defaultExecutionContext
contains as many threads as you have processors. -
Dominykas Mostauskis over 10 years@senia, I have opened a question about why
future { jfuture.get }
is not enough. -
akauppi about 8 yearsYou might want to provide details on what the pros/cons of this are. Is it the exact same as discussed above (in comments e.g. from @senia)
-
Dr.Haribo about 8 yearsSorry about that. Added a comment to explain the use of "blocking".
-
folex almost 8 yearsAnd if you do 'blocking' then you could end up with tens of thousands of threads on high load. Be careful -- 'blocking' is no magic!
-
fcs over 6 yearsThis answer is misleading. scala-java8-compat enables converting from
java.util.concurrent.CompletionStage
toscala.concurrent.Future
. There is no "proper" way to convert a Java Future to Scala Future. -
drobert about 6 yearsThe comment says 'it is non-blocking' but this looks like it would block the executing thread to me.
Try.apply
is a by-name call but that doesn't imply it would execute asynchronously. Promise.complete is similarly blocking. This does wrap the java future's.get
. in an async scalaFuture
, but it would still block the executing thread, similar toFuture { Thread.sleep(10000); }
-
Sky about 6 yearsYes, It will block executing thread but not calling thread. That's intention not block calling thread.