scala.concurrent.Future wrapper for java.util.concurrent.Future

12,479

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

     }
Share:
12,479

Related videos on Youtube

Mark Sivill
Author by

Mark Sivill

Updated on December 04, 2020

Comments

  • Mark Sivill
    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
      Randall Schulz almost 11 years
      Which version of Scala are you using? As of 2.10.x, Scala adopted Akka's Future as its own.
    • Mark Sivill
      Mark Sivill almost 11 years
      Play 2.1.1 uses Scala 2.10.0 under the covers
  • cmbaxter
    cmbaxter almost 11 years
    Agreed. Total shame that the Java future does not support some sort of completion listener/observer for a callback
  • fge
    fge almost 11 years
    @cmbaxter if you use Guava, there is ListenableFuture
  • Mark Sivill
    Mark Sivill almost 11 years
    So 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
    Petr almost 11 years
    I'm curious, what's wrong with future { jfuture.get }? Why you used an extra thread combined with Promise?
  • senia
    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 default ExecutionContext contains as many threads as you have processors.
  • Dominykas Mostauskis
    Dominykas Mostauskis over 10 years
    @senia, I have opened a question about why future { jfuture.get } is not enough.
  • akauppi
    akauppi about 8 years
    You 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
    Dr.Haribo about 8 years
    Sorry about that. Added a comment to explain the use of "blocking".
  • folex
    folex almost 8 years
    And 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
    fcs over 6 years
    This answer is misleading. scala-java8-compat enables converting from java.util.concurrent.CompletionStage to scala.concurrent.Future. There is no "proper" way to convert a Java Future to Scala Future.
  • drobert
    drobert about 6 years
    The 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 scala Future, but it would still block the executing thread, similar to Future { Thread.sleep(10000); }
  • Sky
    Sky about 6 years
    Yes, It will block executing thread but not calling thread. That's intention not block calling thread.