2013-12-11 38 views
2

我正在努力帮助阿卡演员,并确定他们的好处。我知道许多演员可以共享相同的线程,从而获得巨大的效率 - 但在Web应用程序的上下文中,Web容器应该在请求之间做相同的修改?异步I/O是否消耗线程?

因此受益可能回落到I/O - 阻塞I/O暂停线程没有其他人使用。

是否异步I/O消耗螺纹或不?当我得到一些I/O结果的未来时,会在I/O完成时使用一个线程?

回答

6

Java的异步I/O模型在一个很容易的水平掌握描述here。其基本思想是有一个内部线程池,它从内核中检索已完成的I/O通知,然后分派给其他线程以对其执行所需的操作。

所以,从某种意义上说,是的,它使用线程。这里还有其他值得考虑的事情:一切都是如此。每一个软件都需要一个过程,在某个时候,检查一个I/O是否已经完成,以便它可以执行后续任务(当然,它可能会被遗忘,但这是实际起诉有所限制)。在以异步I/O着称的nodejs上,该线程被称为“事件循环”(尽管整体模型非常不同)。

的这里的一点是,没有每个I/O操作一个线程的对应关系。相反,只有一个内部线程池负责接收所有异步I/O完成事件,然后执行完成时所需的任何操作。

也许更好的问题是:在Java中的异步I/O消耗比例的I/O请求的线程数进行处理?不,它没有;它会消耗固定数量的线程。更有用的问题:在Java中启动异步I/O时,是否会阻塞启动I/O的线程?不,不是的;它立即返回。以及相关的问题:Java中的异步I/O使用来自actor线程池的线程吗?不,它没有。

接下来,由异步I/O返回未来。虽然I/O没有完成,但不会使用线程。但是,将有一个线程池分配给该未来的完成,并且当I/O完成时,将使用该池中的一个线程执行与未来完成相关的操作。一旦这些操作完成,该线程将返回到该线程池。该线程池可能不会与演员使用的线程池相同(尽管我想可能有办法让它变成这样)。

+0

我相信akka的'implict val exec = context.dispatcher'意味着IO结果将在相同的线程池中检索。我想改变我的问题,以使比例更加明确,但也许你的答案是“不,它不会占用线程,但它会占用线程”。由于它是深入的,所以标记为答案。 – Stephen

+0

@Stephen可能有一个隐含的,但_Java_不使用implicits,所以它会忽略它。如果您使用其他库中的异步I/O,那么您必须检查自己的文档。 –

+0

太棒了 - 完全忘了Akka也是Java lib吧)。据推测,你仍然可以使用'context.dispatcher'来处理'Future'执行? – Stephen

1

TL; DR上公认的答案:不,线程不由aysnchronous I/O消耗,但线程使用检索从内核的I/O结果。

此外,从Play Framework: async I/O without the thread pool and callback hell

在事件触发的服务器,等待I/O是非常便宜:空闲请求具有成本可以忽略不计,因为他们撑不起来一个线程。

+0

是的,这是正确的 - 但它只适用于*非阻塞* I/O。你不能通过在它上面撒上一些Akka魔法来阻塞I/O进入非阻塞I/O - 它不能像那样工作。这是node.js社区中众所周知的问题,导致许多库被重写为执行异步I/O。在JVM世界中,令人惊讶的是,没有用于异步数据库访问的JDBC的等价物,尽管少数数据库具有可以从Java和Scala使用的异步API。 –

+1

顺便说一下*通过在它上面加上一些魔法来阻止IO进入非阻塞IO * - 是[gevent](http://www.gevent.org/intro.html#monkey-patching)的全部内容当然是Python世界。 –

+0

@ om-nom-nom谢谢,有趣!我正在考虑使用元编程来实现这一点 - 但方式却非常不同。另一个想法,看看! –