This answer指示如何将java.util.concurrent.Future转换为scala.concurrent.Future,同时管理阻止发生的位置:
import java.util.concurrent.{Future => JFuture} import scala.concurrent.{Future => SFuture} val jfuture: JFuture[T] = ??? val promise = Promise[T]() new Thread( new Runnable { def run() { promise.complete(Try{ jfuture.get }) } } ).start val future = promise.future
我的追求与评论中提出的问题相同:
what’s wrong with
future { jfuture.get }
? Why you used an extra thread combined with Promise?
答复如下:
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.
我不知道我理解的解释.重申:
未来{jfuture.get}有什么问题?未来会阻止在手动创建一个新的线程和阻塞吗?如果不是,它是如何不同的?
解决方法
未来{jfuture.get}和未来{future {jfuture.get}}之间几乎没有区别.
默认线程池中有很多脚本,因为有很多处理器.
使用jfuture.get,您将得到1个线程阻塞.
我们假设你有8个处理器.还假设每个jfuture.get需要10秒钟.现在创建8个未来{jfuture.get}.
val format = new java.text.SimpleDateFormat("HH:mm:ss").format(_: Date) val startTime = new Date (1 to 8) map {_ => future{ Thread.sleep(10000) }} future{ 2+2 println(s"2+2 done. Start time: ${format(startTime)},end time: ${format(new Date)}") } // 2+2 done. Start time: 20:48:18,end time: 20:48:28
10秒对于2评估来说有点太长了.
所有其他期货和同一执行环境中的所有参与者将停止10秒钟.
附加执行上下文:
object BlockingExecution { val executor = ExecutionContext.fromExecutor(new ForkJoinPool(20)) } def blockingFuture[T](f: => T) = { future( f )(BlockingExecution.executor) } val startTime = new Date (1 to 8) map {_ => blockingFuture{ Thread.sleep(10000) }} future{ 2+2 println(s"2+2 done. Start time: ${format(startTime)},end time: ${format(new Date)}") } // 2+2 done. Start time: 21:26:18,end time: 21:26:18
您可以使用新的线程(new Runnable {…,但额外的执行上下文允许您限制线程计数)来实现blockingFuture.