Java - 一个while循环(在Therad中)导致Mac上的高CPU

时间:2016-07-02 14:48:08

标签: java multithreading macos while-loop

我需要帮助,

我有这个代码,来自Java游戏开发的教程,
当我运行代码时,while循环(线程)给我的Macbook高CPU。

我已经在Ubuntu vm和Windows 7上运行了这个代码 - 两者都是,CPU很低且正常,
如果这很重要 - 线程大约是27 - (在任务管理器/活动监视器/系统监视器中)。

Mac - CPU正在我的Mac上现在变高89.7,有时超过100:

Mac CPU Image

Ubuntu - CPU在2左右低:

enter image description here

请,

我知道我可以通过睡眠解决这个问题:

thread.sleep(5);

但为什么它在其他操作系统上运行良好? Windows .. Linux .. 我也在其他Macbook Air上测试了这段代码。在另一个Mac上它很高。

有关我的问题的一些信息:

  • 我正在运行mac OSX 10.11.5
  • Java版本:

    java version "1.8.0_91"
    Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
    
  • 代码:

渲染器类:

package org.graphics;

import org.game.Game;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.VolatileImage;

public class Renderer {

    private static Frame frame;
    private static Canvas canvas;

    private static int canvasWidth = 0;
    private static int canvasHeight = 0;

    private static final int GAME_WIDTH = 400;
    private static final int GAME_HEIGHT = 250;

    private static int gameWidth = 0;
    private static int gameHeight = 0;


    private static void getBestSize() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screenSize = toolkit.getScreenSize();

        boolean done = false;

        while (!done) {
            canvasWidth += GAME_WIDTH;
            canvasHeight += GAME_HEIGHT;

            if (canvasWidth > screenSize.width || canvasHeight > screenSize.height) {
                canvasWidth -= GAME_WIDTH;
                canvasHeight -= GAME_HEIGHT;

                done = true;
            }

        }

        int XDiff = screenSize.width - canvasWidth;
        int YDiff = screenSize.height - canvasHeight;
        int factor = canvasWidth / GAME_WIDTH;

        gameWidth = canvasWidth / factor + XDiff / factor;
        gameHeight = canvasHeight / factor + YDiff / factor;

        canvasWidth = gameWidth * factor;
        canvasHeight = gameHeight * factor;

    }

    private static void makeFullScreen() {
        GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = env.getDefaultScreenDevice();

        if (gd.isFullScreenSupported()) {
            frame.setUndecorated(true);
            gd.setFullScreenWindow(frame);
        }
    }

    public static void init() {
        getBestSize();

        frame = new Frame();
        canvas = new Canvas();

        canvas.setPreferredSize(new Dimension(canvasWidth, canvasHeight));

        frame.add(canvas);

        makeFullScreen();

        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);


        frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                Game.quit();
            }


        });

        frame.setVisible(true);

        startRendering();

    }

    private static void startRendering() {
        Thread thread = new Thread() {
            public void run() {

                GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
                VolatileImage vImage = gc.createCompatibleVolatileImage(gameWidth, gameHeight);

                while (true) {
                    if (vImage.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
                        vImage = gc.createCompatibleVolatileImage(gameWidth, gameHeight);
                    }

                    Graphics g = vImage.getGraphics();

                    //Start//

                    g.setColor(Color.black);
                    g.fillRect(0, 0, gameWidth, gameHeight);

                    //end//

                    g.dispose();

                    g = canvas.getGraphics();
                    g.drawImage(vImage, 0, 0, canvasWidth, canvasHeight, null);

                    g.dispose();


                }
            }
        };
        thread.setName("Render Thread");
        thread.start();
    }
}

游戏类:

package org.game;

import org.graphics.Renderer;

public class Game {

    public static void main(String args[]){
        Renderer.init();
    }

    public static void quit(){
        System.exit(0);
    }
}

1 个答案:

答案 0 :(得分:0)

我是创建该教程的人。我想我明白了问题所在。当你在我的CPU之前询问我的时候,我正在检查活动监视器窗口底部的CPU计数器,而不是那个特定进程的计数器。我的误解。

之所以高,是因为我们尚未实施任何类型的睡眠。我打算稍后在关于每秒帧数控制的一集中这样做。在此之前,您的CPU百分比很高是正常的。请记住,可用CPU的总百分比取决于计算机中的核心数。在您的情况下,该程序使用了一个CPU内核的89.7%。

非常感谢您提出这个问题。

编辑:另外,它之所以如此之高是因为我们不告诉它睡觉,它会尽可能快地执行循环,从而产生总数(或几乎总计)使用其中一个CPU核心。