Dom*_*kis 11 java multithreading scala future blocking
此答案指示如何转换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
Run Code Online (Sandbox Code Playgroud)
我的问题与评论中提出的问题相同:
怎么了
future { jfuture.get }?为什么你使用额外的线程与Promise结合?
答案如下:
它会在你的线程拉动中阻止线程.如果您为这样的期货配置了ExecutionContext,那很好,但是默认的ExecutionContext包含与处理器一样多的线程.
我不确定我理解这个解释.重申:
怎么了future { jfuture.get }?在手中创建一个新线程并在那里阻塞时,在未来内部是否阻塞?如果没有,它有什么不同?
future { jfuture.get }和之间几乎没有区别future { future { jfuture.get }}.
默认线程池中有许多踏板,因为有许多处理器.
随着jfuture.get你将获得1个线程被阻止.
假设您有8个处理器.我们假设每个都jfuture.get需要10秒钟.现在创建8 future { 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
Run Code Online (Sandbox Code Playgroud)
10秒对2+2评估来说有点太长了.
future同一执行上下文中的所有其他s和所有actor将被停止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
Run Code Online (Sandbox Code Playgroud)
您可以实现blockingFuture使用new Thread(new Runnable {...,但是额外的执行上下文允许您限制线程数.
它实际上非常简单.scala.concurrent.Promise是a的具体实现Future,注定是异步计算.
当你想转换时jfuture.get,你正在运行一个阻塞计算并输出一个立即解决的scala.concurrent.Future.
在Thread将阻塞,直到计算内jfuture完成.该get方法是阻止的.
阻塞意味着Thread在计算完成之前不会发生任何其他事情.你本质上是垄断了Thread一个看起来像是一个while间歇性检查结果的循环的东西.
while (!isDone() && !timeout) {
// check if the computation is complete
}
Run Code Online (Sandbox Code Playgroud)
特别:
val jfuture: JFuture[T] = ??? // some blocking task
Run Code Online (Sandbox Code Playgroud)
当无法避免阻塞时,通常的做法是生成a new Thread和a new Runnable或new Callable允许计算执行/独占子线程.
在示例中@senia给出:
new Thread(new Runnable { def run() {
promise.complete(Try{ jfuture.get })
}}).start
Run Code Online (Sandbox Code Playgroud)
这有future {jfuture.get}什么不同?它不会阻止ExecutionContextScala提供的默认设置,它具有与计算机处理器一样多的线程.
这意味着代码中的所有其他期货将始终必须等待future { jfuture.get }完成,因为整个上下文都被阻止.
| 归档时间: |
|
| 查看次数: |
1131 次 |
| 最近记录: |