Java在内存分配期间使用多线程

标签 java multithreading memory-management

我目前正在编写一个 java 程序,该程序分配一个大型多维数组进行处理。在分配期间,java 最终使用了所有可用的 CPU(在我的例子中,8 个 CPU)。这是预期的行为吗?我正在使用 Java 版本 1.7.0_65 运行 Ubuntu 14.04。如果您需要更多信息,请告诉我。如果这是预期的行为,是否有办法对其进行限制,使其仅使用一个 CPU?

public class test {
    public static void main(String[] args){
        System.out.println("Test");

        int a = 1000;
        int b = 100;
        int c = 100;
        int d = 1;
        int e = 10;
        float[][][][][] test = new float[a][b][c][d][e];


        System.out.println("Done");
    }
}

编辑:通过将初始堆大小设置得足够大,程序最终不会使用多个 CPU。将来我将同时使用足够大的初始 JVM 大小和 taskset 命令来限制 cpu 亲和性。

最佳答案

分配始终在当前线程中执行,但如果堆上没有足够的空间,分配请求会触发垃圾收集,这取决于 JVM 及其垃圾收集器调整参数,可以使用多个线程。

在 Oracle JVM 上,您可以通过向 Java 进程提供 -verbose:gc 选项来验证情况是否确实如此。在我的电脑上,您的程序会产生以下输出:

Test
[GC (Allocation Failure)  512K->456K(261632K), 0.0007027 secs]
[GC (Allocation Failure)  968K->920K(261632K), 0.0014950 secs]
[GC (Allocation Failure)  1432K->1452K(261632K), 0.0011264 secs]
[GC (Allocation Failure)  1964K->1972K(262144K), 0.0009485 secs]
[GC (Allocation Failure)  2996K->3020K(262144K), 0.0011456 secs]
[GC (Allocation Failure)  4044K->4172K(264704K), 0.0014029 secs]
[GC (Allocation Failure)  6220K->6124K(264704K), 0.0032563 secs]
[GC (Allocation Failure)  8172K->8212K(267776K), 0.0032141 secs]
[GC (Allocation Failure)  11796K->11836K(268288K), 0.0048205 secs]
[GC (Allocation Failure)  15420K->15524K(271872K), 0.0048205 secs]
[GC (Allocation Failure)  20644K->20772K(272896K), 0.0063642 secs]
[GC (Allocation Failure)  25892K->25900K(275968K), 0.0066470 secs]
[GC (Allocation Failure)  33580K->33636K(276480K), 0.0069722 secs]
[GC (Allocation Failure)  41316K->41396K(281088K), 0.0105088 secs]
[GC (Allocation Failure)  52660K->52564K(282112K), 0.0095962 secs]
[GC (Allocation Failure)  63828K->64060K(293376K), 0.0127885 secs]
[GC (Allocation Failure)  81468K->81380K(294400K), 0.0138240 secs]
[GC (Allocation Failure)  98788K->99004K(307712K), 0.0192218 secs]
[GC (Allocation Failure)  122044K->122196K(309248K), 0.0170214 secs]
[GC (Allocation Failure)  145236K->145284K(318976K), 0.0242662 secs]
[GC (Allocation Failure)  174468K->174620K(322048K), 0.0219776 secs]
[GC (Allocation Failure)  203804K->203860K(334336K), 0.0287066 secs]
[GC (Allocation Failure)  241236K->241356K(337920K), 0.0252992 secs]
[GC (Allocation Failure)  278732K->278916K(354816K), 0.0359923 secs]
[Full GC (Ergonomics)  278916K->277284K(400384K), 1.5867443 secs]
[GC (Allocation Failure)  325412K->325695K(404992K), 0.0360435 secs]
[Full GC (Ergonomics)  325695K->325411K(449024K), 0.7776627 secs]
[GC (Allocation Failure)  373539K->373719K(449024K), 0.0383219 secs]
[Full GC (Ergonomics)  373719K->373537K(493056K), 0.8760845 secs]
[GC (Allocation Failure)  414497K->414792K(506368K), 0.0410957 secs]
[Full GC (Ergonomics)  414792K->414495K(553472K), 0.9881370 secs]
[GC (Allocation Failure)  455455K->455705K(549376K), 0.0421990 secs]
[GC (Allocation Failure)  491545K->491545K(557568K), 0.0329242 secs]
[Full GC (Ergonomics)  491545K->491290K(604160K), 1.1687245 secs]
[GC (Allocation Failure)  527130K->527471K(621568K), 0.0546765 secs]
[Full GC (Ergonomics)  527471K->527127K(676864K), 1.2818099 secs]
[GC (Allocation Failure)  565527K->565750K(679424K), 0.0519078 secs]
[GC (Allocation Failure)  604150K->604174K(669184K), 0.0404352 secs]
[GC (Allocation Failure)  623630K->623910K(690176K), 0.0469939 secs]
[Full GC (Ergonomics)  623910K->623379K(753152K), 1.6304653 secs]
[GC (Allocation Failure)  642835K->643153K(751616K), 0.0642752 secs]
[GC (Allocation Failure)  655441K->655473K(760832K), 0.0408013 secs]
[GC (Allocation Failure)  667761K->667761K(760320K), 0.0448666 secs]
[GC (Allocation Failure)  668273K->668273K(773632K), 0.0452070 secs]
[GC (Allocation Failure)  668785K->668785K(784896K), 0.0464397 secs]
[GC (Allocation Failure)  669297K->669297K(785408K), 0.0455053 secs]
[GC (Allocation Failure)  669809K->669841K(799232K), 0.0461530 secs]
[GC (Allocation Failure)  670353K->670401K(696320K), 0.0496845 secs]
[Full GC (Ergonomics)  670401K->669956K(762880K), 1.6411686 secs]
[GC (Allocation Failure)  670468K->670818K(855552K), 0.0602765 secs]
[GC (Allocation Failure)  671842K->671778K(721408K), 0.0332749 secs]
[GC (Allocation Failure)  672802K->672770K(846848K), 0.0333530 secs]
[GC (Allocation Failure)  674306K->674426K(711680K), 0.0328486 secs]
[Full GC (Ergonomics)  674426K->674045K(778240K), 0.6690573 secs]
[GC (Allocation Failure)  675581K->675704K(913408K), 0.0583846 secs]
[GC (Allocation Failure)  676216K->676184K(914944K), 0.0275571 secs]
[GC (Allocation Failure)  676696K->676760K(912896K), 0.0276851 secs]
[GC (Allocation Failure)  677784K->677768K(744448K), 0.0277325 secs]
[GC (Allocation Failure)  678792K->678824K(903168K), 0.0281344 secs]
[GC (Allocation Failure)  680360K->680360K(747520K), 0.0280448 secs]
[GC (Allocation Failure)  681896K->681896K(889856K), 0.0294963 secs]
[GC (Allocation Failure)  683944K->683912K(751616K), 0.0298778 secs]
[GC (Allocation Failure)  685960K->685992K(874496K), 0.0305114 secs]
[GC (Allocation Failure)  688552K->688616K(756736K), 0.0308301 secs]
[GC (Allocation Failure)  691176K->691144K(860160K), 0.0315098 secs]
[GC (Allocation Failure)  694728K->694696K(763904K), 0.0317261 secs]
[GC (Allocation Failure)  698280K->698312K(844800K), 0.0324186 secs]
[GC (Allocation Failure)  702920K->702952K(773120K), 0.0329357 secs]
[GC (Allocation Failure)  707560K->707616K(834048K), 0.0336230 secs]
[GC (Allocation Failure)  713248K->713264K(782336K), 0.0331354 secs]
[GC (Allocation Failure)  718896K->718928K(835072K), 0.0336960 secs]
[GC (Allocation Failure)  726096K->726200K(836608K), 0.0341606 secs]
[GC (Allocation Failure)  733368K->733344K(836608K), 0.0368486 secs]
[GC (Allocation Failure)  740000K->740064K(838656K), 0.0377613 secs]
[GC (Allocation Failure)  746720K->746768K(839680K), 0.0393101 secs]
[GC (Allocation Failure)  750864K->750864K(843776K), 0.0390566 secs]
[GC (Allocation Failure)  754960K->755064K(845312K), 0.0392218 secs]
[GC (Allocation Failure)  756600K->756640K(848896K), 0.0383347 secs]
[GC (Allocation Failure)  758176K->758208K(850432K), 0.0379328 secs]
[GC (Allocation Failure)  759232K->759200K(804864K), 0.0378035 secs]
[GC (Allocation Failure)  760224K->760304K(846848K), 0.0400614 secs]
[GC (Allocation Failure)  761840K->761848K(795136K), 0.0382733 secs]
[GC (Allocation Failure)  763384K->763432K(835584K), 0.0364710 secs]
[GC (Allocation Failure)  765480K->765568K(787968K), 0.0364749 secs]
[GC (Allocation Failure)  767616K->767632K(834048K), 0.0357376 secs]
[Full GC (Ergonomics)  767632K->766656K(881152K), 1.1594624 secs]
[GC (Allocation Failure)  769216K->769444K(882688K), 0.0689485 secs]
[GC (Allocation Failure)  772004K->772044K(884224K), 0.0334374 secs]
[GC (Allocation Failure)  775116K->775188K(884224K), 0.0350246 secs]
[GC (Allocation Failure)  778260K->778300K(881664K), 0.0336294 secs]
[GC (Allocation Failure)  782396K->782396K(810496K), 0.0337357 secs]
[GC (Allocation Failure)  786492K->786524K(877056K), 0.0349286 secs]
[GC (Allocation Failure)  791644K->791684K(816640K), 0.0353728 secs]
[GC (Allocation Failure)  796804K->796876K(869888K), 0.0359552 secs]
[GC (Allocation Failure)  803020K->803068K(820736K), 0.0366515 secs]
[Full GC (Ergonomics)  803068K->802478K(869888K), 1.8098995 secs]
[GC (Allocation Failure)  808622K->808797K(913920K), 0.0726835 secs]
[GC (Allocation Failure)  815965K->815997K(872448K), 0.0363674 secs]
Done

如您所见,JVM 的大部分时间都花在反复尝试垃圾回收上。这是因为 JVM 会在增加堆大小之前首先尝试收集垃圾。您可以通过指示 JVM 从一个适当大的堆开始来避免这种情况。再次假设一个 Oracle JVM,您可以通过在命令行上提供 -Xms1g 来完成此操作。然后,输出要短得多:

Test
[GC (Allocation Failure)  511K->496K(1048064K), 0.0007194 secs]
[GC (Allocation Failure)  1008K->904K(1048064K), 0.0014771 secs]
[GC (Allocation Failure)  1416K->1456K(1048064K), 0.0011328 secs]
[GC (Allocation Failure)  1968K->1996K(1048576K), 0.0011072 secs]
[GC (Allocation Failure)  3020K->3068K(1048576K), 0.0011904 secs]
[GC (Allocation Failure)  4092K->4252K(1051136K), 0.0012557 secs]
[GC (Allocation Failure)  6300K->6148K(1051136K), 0.0033741 secs]
[GC (Allocation Failure)  8196K->8228K(1054208K), 0.0032742 secs]
[GC (Allocation Failure)  11812K->11852K(1054720K), 0.0049498 secs]
[GC (Allocation Failure)  15436K->15604K(1058304K), 0.0042598 secs]
[GC (Allocation Failure)  20724K->20772K(1059328K), 0.0058598 secs]
[GC (Allocation Failure)  25892K->25972K(1062400K), 0.0061824 secs]
[GC (Allocation Failure)  33652K->33700K(1062912K), 0.0076966 secs]
[GC (Allocation Failure)  41380K->41476K(1067520K), 0.0083110 secs]
[GC (Allocation Failure)  52740K->52620K(1068544K), 0.0101210 secs]
[GC (Allocation Failure)  63884K->64060K(1079808K), 0.0126912 secs]
[GC (Allocation Failure)  81468K->81436K(1080832K), 0.0131405 secs]
[GC (Allocation Failure)  98844K->99052K(1093120K), 0.0189248 secs]
[GC (Allocation Failure)  121580K->121684K(1095168K), 0.0154816 secs]
[GC (Allocation Failure)  144212K->144308K(1105408K), 0.0233011 secs]
[GC (Allocation Failure)  173492K->173556K(1107968K), 0.0199322 secs]
[GC (Allocation Failure)  202740K->202860K(1120768K), 0.0276851 secs]
[GC (Allocation Failure)  240236K->240396K(1124352K), 0.0240986 secs]
[GC (Allocation Failure)  277772K->277908K(1140736K), 0.0352077 secs]
[GC (Allocation Failure)  326036K->326180K(1145344K), 0.0325568 secs]
[GC (Allocation Failure)  374308K->374484K(1161728K), 0.0419046 secs]
[GC (Allocation Failure)  431316K->431548K(1167872K), 0.0383821 secs]
[GC (Allocation Failure)  488380K->488580K(1187328K), 0.0488973 secs]
[GC (Allocation Failure)  556676K->556860K(1193472K), 0.0427763 secs]
[GC (Allocation Failure)  624956K->625220K(1216000K), 0.0556787 secs]
[GC (Allocation Failure)  706628K->706852K(1223168K), 0.0524774 secs]
[GC (Allocation Failure)  788260K->788492K(1249792K), 0.0675712 secs]
Done

特别是,没有任何主要的垃圾回收,程序在 CPU 时间的一小部分内完成。

当然,如果在程序运行过程中反复创建这么大的数组,就会出现垃圾回收,暂时使用其他核可能还是要考虑的。在这种情况下,我建议通过其配置选项调整垃圾收集器,以某种方式欺骗 JVM,使其相信可用内核较少,或者在操作系统级别限制 Activity JVM 线程的数量。

关于Java在内存分配期间使用多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25772687/

相关文章:

java - 在 for 循环中扫描输入

java - 将文件读入 CharBuffer,然后 StringBuilder 或 StringBuffer 似乎遗漏了文件的某些部分。为什么?

c# - 从后台线程调用时绑定(bind)失败

c - C 中的动态数组

c++ - 为什么我在检查核心转储时进入 gdb "Cannot access memory at address 0x..."?

java - MongoClient.getDatabase() 是只返回一个数据库实例还是实际创建它?

java - 调用 quit() 后无法使用 WebDriver FirefoxDriver

c# - 多线程增量并在没有锁的情况下跳过0?

multithreading - 如何限制 Erlang VM (BEAM) 使用的内核数量?

ios - 查看 Controller /内存管理