我一直在阅读Play Framework documentation,发现这句话令人困惑:
请注意,您可能想要将阻止代码包装在其中 期货。这不会使它无阻塞,它只是意味着 阻塞将发生在不同的线程中。你还需要做 确保您使用的线程池有足够的线程 处理阻止。
我的印象是所有那些非阻塞的lib都在自己的线程池中执行阻塞操作并返回Future
个对象,因此客户端代码不会被阻塞。
但是这句话说它不会使它无阻塞。我错过了什么吗?是否有一些非阻塞库的高级魔术?
答案 0 :(得分:8)
阻止(如阻止IO )意味着启动IO的线程将进入休眠状态,直到IO结果可用。
非阻塞IO (或异步IO )告诉相关驱动程序(内核,数据库驱动程序等)初始化IO操作然后线程继续做其他事情。根据您使用的技术,您可以在回调(例如Node.js),通道(Java),期货(C ++),promises(Node.js的较新版本)中处理异步IO结果(可能甚至是异常),任务(.Net),协同程序(C ++ 17)等。
异步IO不使用线程使IO异步。这是关键点。向线程池抛出阻塞IO操作不会使其异步,它只是阻塞另一个线程,并且非常不可伸缩。它将使线程池从线程中耗尽,因为它们只会阻塞,因为越来越多的阻塞IO被提交。他们在文档中写道:
典型Play应用程序阻止的最常见位置是 当它与数据库交谈时。不幸的是,没有一个主要的 数据库为JVM提供异步数据库驱动程序
意味着大多数数据库实现不为Java提供异步IO - 将SQL查询抛出到线程池将使线程池线程阻塞。这就是他们的意思:
请注意,您可能想要将阻止代码包装在其中 期货。这不会使它无阻塞,它只是意味着 阻止将发生在另一个线程中。
正如我们之前所说,异步IO 不阻止另一个线程上的IO。
标准包java.nio
提供了Java中 Real 异步IO的示例