Java虚拟机可以维护的最大线程数是多少?
我没有在原始问题中解释这一点,但我正在尝试对JVM进行基准测试,并希望尝试查看它可以同时维护多少个线程。
在循环中创建线程直到抛出异常是一个选项,但是,我想知道是否有更好的方法来执行此操作。
答案 0 :(得分:30)
您的操作系统和硬件配置会受到一些限制。
要提高并发线程数,您应该降低默认的stacksize java -Xss 64k
。
ulimit -a
将为您提供用户进程和内存的配置限制cat /proc/sys/kernel/pid_max
中获得32k个唯一PID - 最多32k个进程。cat /proc/sys/kernel/threads-max
答案 1 :(得分:9)
编写一个创建新线程的循环,直到它爆炸为止是确定的最终方法。在实际死亡之前,您可能会看到性能严重下降。
我不知道JVM中是否有任何配置参数或其他内置限制。我在练习中从未遇到过限制。当然,迟早你会耗尽内存,也许是其他资源。
我怀疑线程数本身没有限制,而是与线程相关的资源。也就是说,你可能会看到你可以拥有10,000个线程,如果它们只运行一个只带有几个字节数据的小类,但当它们各自拥有1000万个字符串的数组时,它会快速下降。
答案 2 :(得分:7)
如果有限制,将由操作系统强加,而不是jvm
答案 3 :(得分:1)
真正的问题不应该是你可以创建多少线程,而是有效运行多少线程。太多的线程,你将导致颠簸,太少和更少的计算时间。
首先,问题,你的线程需要多长时间。短线程不值得努力。另一方面,大型计算具有完美的意义。
其次,每个线程消耗多少内存。获取每个线程所需的内存量,并将其除以可用内存量。你不应该创建比这更多的线程。
第三,您有多少CPU可用。您不应该创建比CPU更多的线程。实际上,您应该考虑至少比线程数少一个。在具有4个CPU的Windows笔记本电脑上,如果需要有效处理,则不应超过3个线程。
最后,你的主题是做什么的。如果它读取和写入硬盘驱动器,那么您可以拥有比CPU数量更多的线程,因为它必须等待设备响应。在确定线程数时请考虑以下方法:
public static int recommendedThreadCount()
{
int mRtnValue = 0;
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long mTotalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
int mAvailableProcessors = runtime.availableProcessors();
long mTotalFreeMemory = freeMemory + (maxMemory - mTotalMemory);
mRtnValue = (int)(mTotalFreeMemory/4200000000l);
int mNoOfThreads = mAvailableProcessors-1;
if(mNoOfThreads < mRtnValue) mRtnValue = mNoOfThreads;
return mRtnValue;
}
答案 4 :(得分:0)
最大线程数也可以由JVM实现限制,cab可以与Java虚拟机不同,也可以与另一个Java虚拟机不同。例如,在Jikes RVM中,数组用于保存有关线程的信息(请参阅Jikes RVM Scheduler source code中的第54行)。在这种情况下,最大线程数不能超过Java中数组的最大大小,大约为2 ^ 32。但是,在达到2 ^ 32个线程之前,您更有可能达到其他操作系统限制或硬件限制。
答案 5 :(得分:0)
最大线程限制主要取决于硬件,操作系统和Java堆栈大小。
以下因素在确定最大线程限制方面起着非常重要的作用:-
2^32
体系结构为32-bit
,2^64
体系结构为64-bit
)java -XX:+PrintFlagsFinal -version | grep -iE 'ThreadStackSize'
PID
限制(可以通过命令“ cat / proc / sys / kernel / pid_max”确定)ulimit -u
因此,最大线程限制为MINIMUM(((进程虚拟地址空间/ java堆栈大小),最大PID
限制,最大进程限制)
例如如果最大进程限制为2048
,并且是上述所有三因素中的最小值,则Java进程将无法创建更多线程。
要进行验证,可以创建一个简单的Java应用程序,在该应用程序中他/她可以在一个循环中创建一个线程,并查看它可以执行多少操作。
示例:
private static Object lock = new Object();
private static int counter = 0;
public static void main(String[] _args) {
while (true) {
new Thread(new Runnable() {
public void run() {
synchronized(lock) {
counter += 1;
System.err.println("New thread #" + counter);
}
while (true) {
try {
Thread.sleep(3000);
} catch (Exception _e) {
_e.printStackTrace();
}
}
}
}).start();
}
}
}
答案 6 :(得分:0)
好吧,如果使用为未来版本的 Java 开发的 Project Loom 技术中的虚拟线程,则数以百万计。
业界更广为人知的名称是 fibers,Loom 项目下的虚拟线程运行在我们在 Java 中已有的“真实”平台/内核线程之上。许多虚拟线程映射到每个平台/内核线程。
虚拟线程提供非常便宜的阻塞。当后台线程上的任务执行文件 i/o、网络调用、数据库访问、日志记录等时,您的代码会阻塞,等待响应。 Project Loom 技术检测到这种阻塞,“停放”(搁置)该虚拟线程,并分配另一个虚拟线程以继续其在平台/内核线程上的工作。这种停车和切换非常快。因此,线程化 Java 应用的性能通常会大幅提升。
因此,主流计算硬件上的 JVM 将能够支持数百万个线程。
注意事项:
使用虚拟线程就像切换 ExecutorService
的实现一样简单:
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
…
有关详细信息,请参阅 this 2021-01-15 article。并观看 Ron Pressler 和其他团队成员的几个非常好的视频演示和采访。随着 Loom 的发展,研究更多最新材料。
基于早期访问 Java 17 的 Project Loom 的实验构建是 available now。团队寻求反馈。