我有以下代码:
def sync = Action {
val t0 = System.nanoTime()
Thread.sleep(100)
val t1 = System.nanoTime()
Ok("Elapsed time: " + (t1 - t0) / 1000000.0 + "ms")
}
def async = Action {
val t0 = System.nanoTime()
Async {
Future{
Thread.sleep(100)
val t1 = System.nanoTime()
Ok("Elapsed time: " + (t1 - t0) / 1000000.0 + "ms")
}
}
}
上述代码之间的区别在于,sync将在接收请求的线程上休眠,async将在单独的线程上休眠,以便负责接收请求的线程可以继续接收请求而不会阻塞。当我描述线程时,我看到为异步请求创建的线程数量突然增加。然而,上述两种具有4000并发连接20秒斜坡的方法导致相同的吞吐量和延迟。我希望异步表现更好。为什么会这样?
答案 0 :(得分:4)
简短的回答是两种方法基本相同。
操作本身始终是异步的(请参阅documentation on handling asynchronous results)。
在这两种情况下,sleep
调用都发生在操作的线程池中(这不是最优的)。
如Understanding Play thread pools中所述:
Play框架是自下而上的异步Web框架。使用迭代器异步处理流。 Play中的线程池被调整为使用比传统Web框架更少的线程,因为play-core中的IO永远不会阻塞。
因此,如果您计划编写阻塞IO代码或可能会执行大量CPU密集型工作的代码,则需要确切地知道哪个线程池承载了该工作负载,并且您需要相应地对其进行调整。
例如,此代码片段使用单独的线程池:
Future {
// Some blocking or expensive code here
}(Contexts.myExecutionContext)
作为其他资源,请参阅this answer和this video,了解有关处理异步操作的更多信息以及this和this论坛消息,以便就此主题进行广泛讨论。