【问题标题】:Java - a while loop (in Therad) causes high CPU just on MacJava - 一个while循环(在线程中)仅在Mac上导致高CPU
【发布时间】:2016-07-02 14:48:08
【问题描述】:

我需要帮助,

我有这段代码,来自 Java 游戏开发教程,
当我运行代码时,while 循环(线程)正在为我的 Macbook 提供高 CPU。

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

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

Ubuntu - CPU 在 2 左右低:

请,

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

thread.sleep(5);

但为什么它在其他操作系统上运行良好?视窗..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);
    }
}

【问题讨论】:

  • 在 Windows 中也是如此。如果你在不睡觉的情况下使用while true,cpu也很高。
  • Game 类的其余部分在哪里?
  • 旁注:在我看来,大多数渲染器的静态成员应该是非静态的
  • @niceman 抱歉,我只是添加其余部分。
  • @x... 请再次检查,运行此代码。或任何其他类似的循环 - youtube.com/watch?v=TNVHWROwYuM

标签: java multithreading macos while-loop


【解决方案1】:

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

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

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

编辑:另外,它如此之高的原因是因为我们不告诉它休眠,它会尽可能快地执行循环,从而导致总(或几乎总)使用其中之一CPU 内核。

【讨论】:

  • 非常感谢塞缪尔。我之所以如此困惑,是因为我看到的每个视频都没有说你应该加入睡眠。我不知道他们是否注意到(我使用笔记本电脑)计算机变得非常热和风扇疯了..
猜你喜欢
  • 1970-01-01
  • 2018-08-19
  • 2012-10-28
  • 1970-01-01
  • 2015-06-27
  • 2015-10-18
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
相关资源
最近更新 更多