CPU上java中可并发运行的最大线程数

CPU上java中可并发运行的最大线程数,java,multithreading,gpu,cpu,Java,Multithreading,Gpu,Cpu,拜托,我有点糊涂了。 我所知道的是,在现代计算机的普通CPU上,可以并发运行的线程的最大数量在8到16个线程之间。 另一方面,使用GPU,数千个线程可以并发运行,而调度程序不会中断任何线程来调度另一个线程。 关于以下几个职位: 人们说他们在普通CPU上同时运行数千个java线程。 这怎么可能?? 我如何知道可以并发运行的最大线程数,以便我的代码根据底层架构自动调整线程数。在任何给定时间,处理器将运行与包含的内核数相等的线程数。这意味着在单处理器系统上,在任何给定时刻只有一个线程(或没有线程)正在

拜托,我有点糊涂了。 我所知道的是,在现代计算机的普通CPU上,可以并发运行的线程的最大数量在8到16个线程之间。 另一方面,使用GPU,数千个线程可以并发运行,而调度程序不会中断任何线程来调度另一个线程。 关于以下几个职位: 人们说他们在普通CPU上同时运行数千个java线程。 这怎么可能??
我如何知道可以并发运行的最大线程数,以便我的代码根据底层架构自动调整线程数。

在任何给定时间,处理器将运行与包含的内核数相等的线程数。这意味着在单处理器系统上,在任何给定时刻只有一个线程(或没有线程)正在运行

然而,处理器并不是一个接一个地运行每个线程,而是在多个线程之间快速切换以模拟并发执行。如果不是这样,更不用说创建多个线程了,您甚至无法启动多个应用程序

java线程(与处理器指令相比)是CPU要处理的一组指令的高级抽象。当它到达处理器级别时,无法保证在任何给定时间哪个线程将在哪个内核上运行。但考虑到处理器在这些线程之间快速切换,理论上可以创建无限多的线程,尽管会以性能为代价

如果你仔细想想,一台现代计算机有数千个线程同时运行(组合所有应用程序),而只有1~16个(典型情况)核。如果没有这个任务切换,什么事情也做不成


<>如果你在优化你的应用程序,你应该考虑手头的工作需要的线程数量,而不是底层架构。并行性带来的性能增益应该与线程执行开销的增加相权衡。由于每台机器都不同,每种运行时环境都不同,因此计算一些黄金线程数是不切实际的(但是,通过基准测试和查看内核数量可以做出大致估计)。

存在硬件和软件并发性。8到16个线程指的是您拥有的硬件,即一个或多个CPU,其硬件可相互并行执行8到16个线程。数千个线程指的是软件线程的数量,调度程序必须将它们调出,以便每个软件线程都能在硬件上运行


要获取硬件线程的数量,可以尝试运行时。可用处理器()

线程不受可用处理器/内核数量的限制。操作系统调度程序可以在单个CPU上任意数量的线程之间来回切换。这就是“先发制人的多任务处理”的含义

当然,如果线程多于内核,则并非所有线程都将同时执行。有些人会等待,等待一个时间段

实际上,您可以拥有的线程数量受到调度程序的限制,但这个数量通常非常高(数千个或更多)。不同的操作系统和不同的版本会有所不同


从性能的角度来看,有多少线程是有用的,正如您所说,这取决于可用处理器的数量以及任务是IO还是CPU绑定的。尝试找到最佳数量,并尽可能使其可配置。

而所有其他答案都解释了如何在理论上以内存和其他开销为代价在应用程序中拥有数千个线程。但是值得注意的是,
java.util.concurrent
包中提供的数据结构的默认
concurrencyLevel
为16

如果你不考虑同样的问题,你会遇到争论的问题

使用比您需要的值高得多的值可能会浪费空间和时间,而低得多的值可能会导致线程争用


确保设置了适当的
并发级别
,以防遇到与线程数较多的并发相关的问题。

理论上,您可以运行任意数量的线程,但当JVM努力跟踪调度时,您会遇到越来越多的开销,在任何给定时刻,只有一个线程正在运行-更像是“一个线程或没有线程”。@MartinJames-response-fixed。除非通过硬件或软件中断进入操作系统,否则调度程序将不执行任何操作。“数千个线程”大多还没有准备好运行,因此不需要任何“时间片”在硬件上运行。@MartinJames除非您的操作系统在协作线程上运行,否则总会有一个cpu计时器通过硬件中断触发调度程序。线程是否准备好运行取决于它们所做的事情,如果它们所做的只是睡眠,那么拥有数千个线程仍然是浪费(每个线程都有一个堆栈和管理结构)。可以在没有计时器中断的情况下操作抢占式多任务操作系统。启动调度程序运行的另一种方法,即磁盘中断、NIC中断、KB中断、鼠标中断、I/O请求中断和线程间同步中断非常重要。计时器只是另一个中断源,忽略其他中断源是不好的。另外-你知道堆栈是可交换的吗?@MartinJames只要准备运行的线程总是少于可用的硬件,那么使用计时器是不必要的,这是正确的,一旦你得到更多,一些进程可能会饿死。关于堆栈问题:堆栈占用内存,数千个线程可以很快占用2GB或更大的内存,而将它们调出只会降低切换回内存的速度