非阻塞API如何工作?

时间:2016-12-19 16:44:01

标签: java multithreading asynchronous nonblocking

我一直在阅读Play Framework documentation,发现这句话令人困惑:

  

请注意,您可能想要将阻止代码包装在其中   期货。这不会使它无阻塞,它只是意味着   阻塞将发生在不同的线程中。你还需要做   确保您使用的线程池有足够的线程   处理阻止。

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

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

1 个答案:

答案 0 :(得分:8)

从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查询抛出到线程池将使线程池线程阻塞。这就是他们的意思:

  

请注意,您可能想要将阻止代码包装在其中   期货。这不会使它无阻塞,它只是意味着   阻止将发生在另一个线程中。

正如我们之前所说,异步IO 阻止另一个线程上的IO。

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