在java中,应用程序中CPU核心数与线程数之间的关系是什么?

时间:2014-01-16 09:40:25

标签: java multithreading sockets networking

我是java 多线程编程的新手。我想到的问题是我可以根据 CPU内核的数量运行多少个线程。如果我运行的线程超过 CPU核心,那么它将成为机器运行应用程序的开销。例如,当我们的服务器机器有一个运行2个线程的服务器软件(主线程+开发人员线程)时,当更多的并发客户端与服务器建立套接字连接时,它是否会成为服务器的开销?

感谢。

7 个答案:

答案 0 :(得分:9)

系统可以同时执行的线程数(当然)与系统中的核心数相同。

系统上可以存在的线程数受可用内存的限制(每个线程需要一个堆栈和操作系统用来管理线程的结构),并且可能限制了OS允许的线程数量(这取决于操作系统架构,某些操作系统可能会使用固定大小的表,一旦完整,就不会再创建线程了。)

通常,今天的计算机可以处理数百到数千个线程。

系统中存在比核心使用更多线程的原因是:大多数线程将不可避免地花费大量时间等待来处理某些事件(例如:字处理器等待用户在键盘上键入)。操作系统管理它以这种方式等待的线程不消耗CPU时间。

答案 1 :(得分:4)

这取决于线程正在做什么。 CPU只能同时执行X事务,其中X是它拥有的核心数。这意味着任何时候X线程最多都可以处于活动状态 - 但是其他线程可以等待轮到它们,CPU会在适当的时候处理它们。

您还应该考虑很多时候线程正在等待响应,或者等待数据加载,或者网络消息到达等等,所以实际上并没有尝试做任何事情。这些空闲/等待线程对系统的负载非常小。

答案 2 :(得分:4)

它背后的想法是不要让你的CPU睡眠,也不要加载过多而浪费大部分时间在线程切换中。

检查 Tuning the pool size, In IBMs paper

是有帮助的

背后的理念是,它取决于任务的性质,如果它的所有内存计算任务都可以使用N + 1个线程(N个核心数(包括超线程))。

我们需要进行应用程序分析,找出典型请求的等待时间(WT),服务时间(ST)以及我们可以拥有的大约N *(1 + WT / ST)个最佳线程数,考虑100%利用CPU。

答案 3 :(得分:3)

不要担心获得比CPU核心更多的线程;这实际上并不在你手中,而是在OS'中。

假设JVM通过OS线程映射你的java线程(这些天很平常),它取决于你的操作系统的线程管理。在那里,您依赖于内核实现的智能程度,以便从内核中获得性能。

您必须牢记的是您的设计必须是可持续的。例如,应用程序服务器构建在充满工作线程的线程池上。这些线程被唤醒以便提供请求。你想为每个请求一个线程吗?然后你肯定会有一个问题 - 请求可以成千上万地到达服务器,这可能是内核管理的问题。实际上线程池大小应该是有限的(在1和X之间,甚至可以在实时中轻松更改),线程应该从并发队列中获得工作(java为您提供了一些优秀的类),并且每个线程按顺序参与请求。

我希望得到帮助

答案 4 :(得分:2)

线程少于CPU可能意味着您没有使用系统中的所有CPU。如果CPU是您的瓶颈,拥有更多线程可能会提高吞吐量。

拥有比CPU更多的线程会带来开销,如果CPU是你的瓶颈,这可能会影响性能。但是,如果网络IO是您的瓶颈,那么这种开销是值得付出的代价,因为它通常允许您处理更多连接。例如您可以使用自己的线程拥有1000个TCP连接。

答案 5 :(得分:0)

最佳性能将是核心数量( NOC )等于线程数(),因为如果不是> NOC然后处理器应该切换上下文或OS会尝试做那项工作,这是足够昂贵的操作。但是你必须明白,在Web服务器上不可能有NOC = NOT,因为你无法预测同时会有多少客户端。看一下load balancing概念,以最佳方式解决这个问题。

答案 6 :(得分:0)

没有任何关系。一台计算机可以具有任意数量的内核。一个进程可以具有任意数量的线程。

进程使用线程有多种不同的原因,包括:

  • 编程抽象。划分工作并将每个划分分配给一个执行单元(一个线程)是解决许多问题的自然方法。利用这种方法的编程模式包括反应器,每个连接线程和线程池模式。但是,有些人将线程视为反模式。独特的Alan Cox用这样的话概括了这一点:“线程是为无法对状态机进行编程的人的。”

  • 阻止I / O 。没有线程,阻塞I / O会暂停整个过程。这可能对吞吐量和延迟均有害。在多线程进程中,单个线程可能会阻塞,等待I / O,而其他线程会向前推进。因此,通过线程阻止I / O是异步和非阻止I / O的替代方法。

  • 内存节省。线程提供了一种共享内存但利用多个执行单元的有效方法。通过这种方式,它们可以替代多个过程。

  • 并行性。在具有多个处理器的计算机中,线程提供了一种实现真正并行性的有效方法。由于每个线程都拥有自己的虚拟处理器,并且是一个可独立调度的实体,因此多个线程可以同时在多个处理器上运行,从而提高了系统的吞吐量。在某种程度上,线程用于实现并行性(即,线程不比处理器多),“线程用于无法编程状态机的人”的引用不适用。

前三个项目符号使用与内核无关的线程。例如,如果您使用线程作为处理UI元素的编程抽象,则每个UI元素(或其他任何元素)将只有一个线程,而不管您有1个内核还是12个内核。类似地,如果您使用线程执行阻塞I / O,您将根据I / O容量而不是处理能力来扩展线程数。

但是,第四个项目符号确实将线程与内核相关联。如果线程化的目标是并行性,则线程数应与内核数成线性比例。例如,如果您将系统中的内核数加倍,那么您将使应用程序中的线程数加倍。从逻辑上来说,包括SMT在内的内核都是如此。

当使用线程来实现并行性时(这是线程的常见也是最好的用法),每个内核通常会有一个或两个线程。通常,编写应用程序是为了根据可用核的数量动态调整线程池的大小。每个内核有一个单线程是理想的选择,但是应用程序通常会使用较大的乘数,例如每个内核有两个线程,这是由于其代码中的错误和效率低下(例如在没有响应时会阻塞的操作)。