Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 每请求线程模型能比非阻塞I/O更快吗?_Java_Multithreading_Pthreads_Nio - Fatal编程技术网

Java 每请求线程模型能比非阻塞I/O更快吗?

Java 每请求线程模型能比非阻塞I/O更快吗?,java,multithreading,pthreads,nio,Java,Multithreading,Pthreads,Nio,我记得两三年前读过几篇文章,其中有人说现代线程库变得非常好,每个请求线程服务器不仅比非阻塞服务器更容易编写,而且速度也更快。我相信这甚至在Java中通过一个将Java线程映射到pthreads的JVM得到了证明(即Java nio开销大于上下文切换开销) 但现在我看到所有的“尖端”服务器都使用异步库(JavaNIO、epoll,甚至node.js)。这是否意味着async赢了?只要有足够的内存,它就会更快 当有太多的连接(其中大多数是空闲的)时,NIO可以节省线程,从而节省内存,并且系统可以处理

我记得两三年前读过几篇文章,其中有人说现代线程库变得非常好,每个请求线程服务器不仅比非阻塞服务器更容易编写,而且速度也更快。我相信这甚至在Java中通过一个将Java线程映射到pthreads的JVM得到了证明(即Java nio开销大于上下文切换开销)


但现在我看到所有的“尖端”服务器都使用异步库(JavaNIO、epoll,甚至node.js)。这是否意味着async赢了?

只要有足够的内存,它就会更快

当有太多的连接(其中大多数是空闲的)时,NIO可以节省线程,从而节省内存,并且系统可以处理比每个连接模型的线程多得多的用户

CPU不是这里的直接因素。使用NIO,您实际上需要自己实现一个线程模型,这不可能比JVM的线程更快


无论哪种选择,内存都是最终的瓶颈。当负载增加且使用的内存接近最大值时,GC将非常繁忙,系统通常表现出100%CPU的症状。

我认为不是这样。如果这两个模型都得到很好的实现(这是一个很大的要求),我认为NIO的概念应该占上风

计算机的核心是核心。无论您做什么,您的应用程序的并行化都不能超过您的核心。i、 如果你有一台4核的机器,你一次只能做4件事(我在这里略述了一些细节,但这就足够了)

扩展这个想法,如果你的线程比内核多,你就浪费了。这种浪费有两种形式。首先是额外线程本身的开销。其次是在线程之间切换所花费的时间。两者都可能是次要的,但它们确实存在

理想情况下,每个核心只有一个线程,并且每个线程在其核心上以100%的处理速度运行。在理想情况下,任务切换不会发生。当然有操作系统,但是如果你用一台16核的机器,为操作系统留下2-3个线程,那么剩下的13-14个线程将用于你的应用程序。这些线程可以在你的应用程序中切换它们正在做的事情,比如当它们被IO要求阻止时,但不必在操作系统级别支付该成本。将其直接写入应用程序

SEDA就是这种扩展的一个很好的例子。它在负载下显示出比标准的每请求线程模型更好的可伸缩性

我个人的经历是和内蒂在一起。我有一个简单的应用程序。我在Tomcat和Netty中都很好地实现了它。然后我用100个并发请求(我相信超过800个)对它进行了负载测试。最后,Tomcat慢下来爬行,表现出极其暴躁/迟钝的行为。而Netty实现只是增加了响应时间,但总体吞吐量却令人难以置信


请注意,这取决于可靠的实施。随着时间的推移,NIO仍在好转。我们正在学习如何调整服务器操作系统以更好地使用它,以及如何实现JVM以更好地利用操作系统功能。我认为还不能宣布胜利者,但我相信NIO将是最终的胜利者,而且它已经做得很好。

不久前,我发现提供了一些关于“为什么旧的每客户端线程模式更好”的见解。甚至还有测量。不过我还在想。在我看来,这个问题的最佳答案是“视情况而定”,因为大多数(如果不是全部的话)工程决策都是权衡取舍。

就像那篇演讲中所说的那样——既有速度,也有可扩展性


在一种情况下,每个请求的线程速度几乎肯定会比任何异步解决方案都快,即当您的客户端数量相对较少时(例如,这是有意义的。快速谷歌搜索显示,64位机器上每个线程的热点默认堆栈为1MB)(我知道这不是堆,但它会减少为堆保留的内存量)。这本身就意味着每个请求的线程数不适合C10K,至少在Java中是这样。但如果内存是约束条件,那么它可能适合数百个并发连接。这是一个非常有趣的现实测试。对于许多应用程序来说,800个并发请求真的不是那么多。我想知道Tomcat中的延迟是否是由于contex造成的t开关(或GC,如@unreputable所示),这意味着每个请求的线程模型本身存在故障,而不是它的Tomcat实现。公平地说,这是一个正在测试的单服务器,而不是群集。至于800个请求。根据我的经验,800个并发请求相当高。区分并发请求和连接很重要。如果你得到响应时间在100毫秒的负载范围内,你每秒支持8k个请求。这对一个盒子来说并不坏。扩展一整天,你就可以用一台服务器处理7亿个请求。没有多少应用程序需要这么多。我想这可能是我记忆中的演示。这些观察结果(nio可能很慢)再加上在Erlang和Scala中对基于参与者的并发性的新认识,使我认为世界正在向同步模型发展。但是在这些语言之外(Scala的大部分都是欺骗),我认为我会坚持使用同步作为默认值,直到遇到像@rfeak遇到的那些实际问题。