非阻塞API如何工作?

sil*_*box 6 java multithreading asynchronous nonblocking

我一直在阅读Play Framework文档,发现这个引用令人困惑:

请注意,您可能想要将您的阻止代码包装在Futures中.这不会使它成为非阻塞,它只是意味着阻塞将在不同的线程中发生.您仍然需要确保您使用的线程池有足够的线程来处理阻塞.

我的印象是所有那些非阻塞的lib都在他们自己的线程池中执行阻塞操作并返回Future对象,因此客户端代码不会被阻塞.

但是这句话说它并没有使它无阻塞.我错过了什么吗?是否有一些非阻塞库的高级魔术?

Dav*_*aim 10

IO意义上阻塞(如在阻塞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查询抛出到线程池会使线程池线程阻塞.这就是他们的意思:

请注意,您可能想要将您的阻止代码包装在Futures中.这不会使它成为非阻塞,它只是意味着阻塞将在不同的线程中发生.

正如我们之前所说,异步IO 不会在另一个线程上阻塞IO.

标准软件包提供了Java中的Real异步IO 示例java.nio