Java 8自动使用多核



一年前我用java7做了一些关于多核的测试。首先,我只在主线程中实现了一些计算(CPU使用情况显示只有一个内核完成了所有工作),然后我用ExecutiorService实例实现了Callable。运行时,所有核心都在哪里工作。

现在,一年后,我必须实现一个小程序(使用java8),它可以插入大量数据。所有的工作都是在主线程中实现的(没有Callable和ExecutorService),但当我运行程序时,CPU使用率显示,所有4个内核都达到了98%。

那么,java 8是否会自动将工作分配到所有CPU内核上?我很困惑。。。

这里有一些代码。。。

MapGenerator.java

    Region[][] regions = new Region[numOfRegions][numOfRegions];
    for(int x = 0; x < regions.length; x++){
        for(int z = 0; z < regions[x].length; z++){
            newLat = SRTMHandler.getNewLatitude(startLat, z * regionSize * 16);
            newLon = SRTMHandler.getNewLongitude(startLon, x * regionSize * 16, newLat);
            regions[x][z] = new Region(x, z, regionSize, newLat, newLon);
        }
    }

Region.java:

private Chunk[] chunks;    
public Region(int x, int z, int size, float startLat, float startLon){
    this.chunks = new Chunk[this.size][this.size];
    //Init stuff
    float newLat = this.startLat, newLon = this.startLon;
    for(int newX = 0; newX < this.size; newX++){
        for(int newZ = 0; newZ < this.size; newZ++){
            newLat = SRTMHandler.getNewLatitude(this.startLat, newZ * 16);
            newLon = SRTMHandler.getNewLongitude(this.startLon, newX * 16, newLat);
            this.chunks[newX][newZ] = new Chunk(this.x * this.size + newX, this.z * this.size + newZ, 16, 900, this, newLat, newLon);
        }
    }
}

Chunk.java:(SRTMHandler.getHeightForLatLon()进行一些地理计算,然后读取字节数组中的值,没有什么特别的)

public Chunk(int x, int z, int size, int height, Region r, float startLat, float startLon){
    this.blocks = new Block[size][size][height];
    //Init stuff
    try {
        this.calcSurface();
        //System.out.println("Finished " + this.toString());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
private void calcSurface() throws IOException{
    int x1 = this.x;
    int x2 = this.x + 16;
    int z1 = this.z;
    int z2 = this.z + 16;
    final int radius = 45;
    float q11 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, (-1)*radius), SRTMHandler.getNewLongitude(this.startLon, (-1)*radius, this.startLat));
    float q12 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, radius), SRTMHandler.getNewLongitude(this.startLon, (-1)*radius, this.startLat));
    float q21 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, (-1)*radius), SRTMHandler.getNewLongitude(this.startLon, radius, this.startLon));
    float q22 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, radius), SRTMHandler.getNewLongitude(this.startLon, radius, this.startLat));
    for(int x = 0; x < this.blocks.length; x++){
        for(int z = 0; z < this.blocks[x].length; z++){
            float height = Interpolation.biLerp(x, z, q11, q12, q21, q22, x1, x2, z1, z2);
            this.blocks[x][z][(int)Math.round(height)] = new Block(this.x * this.size + x, this.z * this.size + z, (int)Math.round(height), BlockType.Grass, this);
        }
    }
}

Java 8不会自动将工作分配到所有CPU核心上,除非您的代码明确请求(例如使用并行流)。

在某些特殊情况下,Hotspot编译器会自动向量化代码,例如参见JDK-6340864。然而,自动矢量化是使用特殊的SIMD CPU指令,而不是多个CPU。

另请参阅以下答案:

  • JVM是否有能力检测并行化的机会
  • 自动并行化

(注意,我重写了答案,删除了注释中更正的部分)

我也经历过这种情况。在我的案例中,正是频繁的垃圾收集导致了相当高的CPU使用率(98%)。正如在原始问题下的几个注释所指出的,javaGC默认使用多线程。

在我看来,您的程序不受CPU限制。因此,不太可能完全使用4个核心。另一方面,当没有足够的堆空间分配给程序时,频繁的GC会很容易耗尽CPU资源。增加堆大小后,一切都很好。

相关内容

  • 没有找到相关文章

最新更新