Java 服务器和线程模型

Java 服务器和线程模型,java,c++,multithreading,performance,Java,C++,Multithreading,Performance,我对以下概念感到困扰: 大多数书籍/文档都描述了多线程服务器的健壮性,最常见的方法是启动一个新线程为每个新客户机提供服务。例如,每个新连接专用一个螺纹。但这在大系统中是如何实现的呢?如果我们有一个服务器可以接受100000个客户端的请求,那么它已经启动100000个线程了?这现实吗?服务器中可以运行的线程数量没有限制吗?此外,上下文切换和同步的开销会降低性能吗?它是作为队列和线程的混合实现的吗?在这种情况下,队列的数量是固定的吗?有谁能在这方面给我一些启发,也许能给我一个很好的参考来描述这些 谢

我对以下概念感到困扰: 大多数书籍/文档都描述了多线程服务器的健壮性,最常见的方法是启动一个新线程为每个新客户机提供服务。例如,每个新连接专用一个螺纹。但这在大系统中是如何实现的呢?如果我们有一个服务器可以接受100000个客户端的请求,那么它已经启动100000个线程了?这现实吗?服务器中可以运行的线程数量没有限制吗?此外,上下文切换和同步的开销会降低性能吗?它是作为队列和线程的混合实现的吗?在这种情况下,队列的数量是固定的吗?有谁能在这方面给我一些启发,也许能给我一个很好的参考来描述这些


谢谢

常用的方法是使用线程池。线程池是已创建线程的集合。当新请求到达服务器时,会从池中为其分配一个备用线程。处理请求时,线程返回池

池中的线程数根据应用程序的特征进行配置。例如,如果您有一个CPU受限的应用程序,您将不需要太多线程,因为上下文切换会降低性能。另一方面,如果你有一个DB或IO绑定的应用程序,你需要更多的线程,因为等待的时间太长了。因此,更多的线程将更好地利用CPU


谷歌“线程池”,你肯定会找到很多关于这个概念的阅读资料。

在大多数系统中都使用线程池。这是等待传入请求的可用线程池。线程的数量可以增长到配置的最大数量,这取决于同时传入的请求数量和应用程序的特征

如果请求到达,则从线程池中请求一个未占用的线程。然后,该线程专用于处理请求,直到请求完成。发生这种情况时,线程将返回到线程池以处理另一个请求

由于线程的数量有限,在大多数服务器系统中,应该尽量缩短请求的生存期。执行请求所需的时间越短,线程就越快可以用于新请求

如果请求是在所有线程都被占用的情况下传入的,那么大多数服务器都会对请求实施排队机制。当然,队列的大小也是有限的,因此当到达的请求超过可以排队的数量时,新的请求将被拒绝


使用线程池而不是为每个请求启动线程的另一个原因是,启动新线程是一项昂贵的操作。最好事先启动多个线程,并重复使用它们,然后一直启动新线程。

还要阅读SEDA模式,

除了上面我应该注意到的答案之外,具有许多传入连接的真正高性能服务器不会尝试为每个连接生成一个线程,而是使用IO完成端口、select()和其他异步技术在一个线程中处理多个套接字。当然,必须特别注意确保一个请求或一个套接字的问题不会阻塞同一线程中的其他套接字


线程管理也会消耗CPU时间,因此不应该为每个连接或每个客户端请求生成线程

要让网络服务器处理大量并发连接,有几种方法(主要分为“每个连接一个线程”和“每个线程几个连接”两类),请看,这是本主题的一个重要资源,讨论和比较许多方法,并链接到有关它们的更多资源。

在大多数情况下,创建10k线程不太可能是有效的,但可以做到,而且会奏效

如果您需要同时为10k客户机提供服务,那么在一台机器上这样做是不太可能的,但也是可能的

根据客户端实现的不同,10000个客户端可能不需要维护开放的TCP连接-根据目的,协议设计可以大大提高实现的效率


我认为适用于大规模系统的适当解决方案可能是非常特定于领域的,如果您想得到建议,您必须详细解释您的问题领域。

a.NET线程的堆栈大小为1MB,100000个线程需要100GB的RAM才能保持线程的运行,显然不现实。@Kristofer:看看线程池,我的理解是池中线程的数量应该始终与可用处理器的数量相关。如果是这样,那么池中的线程数相对于请求数总是较低的。如果我的理解是正确的,那么在我的示例中,在一台拥有48个核心处理器的机器中,应该只对48个线程进行池处理,其余的请求应该排队?我是否混淆了这些概念?在决定所需的线程数量时,您应该始终考虑可用的处理器数量。但是,您还需要考虑线程所做的工作类型。让我们举两个例子。1) 线程只执行需要CPU的计算,不需要IO或其他等待。那么,拥有与CPU相同数量的线程是有意义的,因为这样可以避免在空闲时浪费CPU周期,同时最小化上下文切换。2) 线程有50%的时间等待外部系统。那么有2个线程来充分利用CPU是有意义的。@Kristofer:好的,这就是我从线程池中了解到的。但是,在一个请求数很高的示例中(例如10000),如果池中的线程数与可用线程数相关,这意味着有很高比例的请求将一直排队?是的,那么它们将排队(或者如果