运行 Java 应用程序时 GPU 使用率高

问题描述

我最近注意到运行 Java 应用程序时常见的延迟峰值。滞后峰值大约每 10-15 秒发生一次,并持续 1-5 秒。我认为这可能是因为我正在创建很多流程。所以我创建了一个简单的 Java 应用程序,它只是创建了一个窗口:

public class Main extends Canvas {
    private static final long serialVersionUID = 1L;
    public JFrame frame = new JFrame();
    public Main() {
        frame.add(this);
        frame.setSize(1000,750);
        frame.setLocationRelativeto(null);
        frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        new Thread(() -> run()).start();
    }
    public void run() {
        boolean running = true;
        while(running) {
            BufferStrategy bs = getBufferStrategy();
            if(bs != null) {
                Graphics g = bs.getDrawGraphics();
                render(g);
                g.dispose();
                bs.show();
            } else {
                createBufferStrategy(3);
            }
        }
    }
    public void render(Graphics g) {
        g.setColor(Color.green);
        g.fillRect(0,getWidth(),getHeight());
    }
    
    public static void main(String[] args) {
        new Main();
    }
}

当我运行它时,GPU 使用率从 0-3% 一路上升到 95-100%。如果我不创建线程(在 Main() 的末尾),GPU 根本不会受到影响,但现在我无法在窗口上渲染任何内容。我认为这与 BufferStrategy 有关,但我不确定。我的 GPU 是 NVIDIA GeForce GTX 1660 Ti,我的操作系统是 Windows 10 Home。所以我的问题是:为什么 GPU 使用率这么高,我该如何解决

解决方法

看起来 while(running) 执行的调用过多,因为它将运行到系统的最大容量(可能超过 60 FPS!)。

也许您应该只通过某种计时器每 60 FPS 进行一次调用,而不是使用“残酷的”while 循环? 看起来这可以解决您的问题:How do I set up a JFrame with a refresh rate?

,

这从根本上误解了 Swing 中的 JFrame 应该如何工作。通过使用 swing,您可以让操作系统(和 VM)处理交互和渲染。根本不需要手动渲染线程。

相反,您应该覆盖 paintComponent 函数并使用该图形对象进行渲染(不要忘记调用 super 函数以及渲染其他位)。当需要图形绘制时,系统会调用它。

只有当您尝试手动将视频渲染到 JFrame 时,才有意义。但即便如此,最好的方法还是使用现有的组件库来为您处理。