我想限制Java VM可用的线程/进程数,类似于设置可用内存的方式。我希望能够指定它只使用1个线程或任意数字。
注意:我无法在代码中设置它,因为我想限制的代码是一个我无法修改源代码的库。因此,它必须是强加于虚拟机级别的硬限制。 (或者,如果您可以对应用程序本身施加可以覆盖库的线程限制?)
注意2:这是一个性能测试,用于限制我想要测试的库,以查看当它可以访问不同数量的CPU /线程时它的性能。
谢谢!
没有VM标志或属性来控制Java可用的CPU数量,即Runtime.availableProcessors()
返回的数量。
在Windows和Solaris上,如果设置了进程关联掩码,它也会影响Runtime.availableProcessors()
。这在Linux上不起作用,请参阅JDK-6515172。不幸的是,修复程序仅针对Java 10,但建议的修补程序包含在错误讨论中。
使用LD_PRELOAD补丁或操作系统级别的技巧也可以解决Linux的问题,请参阅this question中的详细信息。
我建议您可以实现并安装自己的SecurityManager,它跟踪创建的线程数,并在达到最大值时抛出错误。
根据this question接受的答案,每次创建/启动新线程时都会检查带有“modifyThreadGroup”目标的RuntimePermission
。
更新
SecurityManager的第一种方法可能是这样的:
class MySecurityManager extends SecurityManager
{
private final int maxThreads;
private int createdThreads;
public MySecurityManager(int maxThreads)
{
super();
this.maxThreads=maxThreads;
}
@Override
public void checkAccess(Thread t)
{
// Invoked at Thread *instantiation* (not at the start invokation).
super.checkAccess(t);
// Synchronized to prevent race conditions (thanks to Ibrahim Arief) between read an write operations of variable createdThreads:
synchronized(this)
{
if (this.createdThreads == this.maxThreads)
{
throw new Error("Maximum of threads exhausted");
}
else
{
this.createdThreads++;
}
}
}
}
对于corse,必须进行进一步的测试以保证始终允许系统线程。并且仍然认为该算法在线程结束时不会减少计数。
尝试使用“亲和力”为Windows用户运行程序。
例如:当你需要1个核心时,你应该运行:“start / affinity 1 java Test”,而不是运行“java Test”;当你需要2个核心时,“start / affinity 3 java Test”; ....使用的参数应遵循以下形式:
您可以使用“System.out.println(Runtime.getRuntime()。availableProcessors());来检查。
作为最后的手段,我可以将Java VM在任务管理器中的亲和力设置为仅使用1个(或更多)CPU。 (这当然仍然允许1个CPU上的多个线程,但如果没有其他任何更好的想法,它可能是我想要的最接近的东西)
JVM中的CPU限制问题在Java 10中得到解决,并从build 8u191向后移植到Java 8:
-XX:ActiveProcessorCount=2