如何阻止 Java while 循环占用>50% 的 CPU?
好吧,我在一个空程序上测试了这个,只是运行了一段时间(true){}就给了我>50%的CPU。我正在开发一个游戏,它使用while循环作为主循环,并且它的CPU始终处于100。
我怎样才能让Java一遍又一遍地重复一些事情,而不会消耗掉>50%的CPU来执行重复?
好吧,我在一个空程序上测试了这个,只是运行了一段时间(true){}就给了我>50%的CPU。我正在开发一个游戏,它使用while循环作为主循环,并且它的CPU始终处于100。
我怎样才能让Java一遍又一遍地重复一些事情,而不会消耗掉>50%的CPU来执行重复?
添加一个睡眠以将线程置于空闲状态一段时间:
如果没有休眠状态,while 循环将消耗所有可用的计算资源。(例如,从理论上讲,单核系统中为 100%,双核系统中为 50%,依此类推。
例如,以下内容将大约每 50 毫秒循环一次循环:while
while (true)
{
try
{
Thread.sleep(50);
}
catch (Exception e)
{
e.printStackTrace();
}
}
这应该会大大降低CPU利用率。
在循环中休眠的情况下,操作系统还将为其他线程和进程提供足够的系统时间来执行其操作,因此系统也将响应。回到单核系统和操作系统具有不太好的调度程序的时代,像这样的循环可能会使系统非常无响应。
由于出现了游戏使用循环的主题,因此如果游戏将涉及GUI,则游戏循环必须位于单独的线程中,否则GUI本身将变得无响应。while
如果程序将是一个基于控制台的游戏,那么线程化不会成为问题,但是对于事件驱动的图形用户界面,在代码中具有长期存在的循环将使GUI无响应。
线程化等是编程中非常棘手的领域,尤其是在入门时,因此我建议在必要时提出另一个问题。
下面是基于 的 Swing 应用程序的示例,该应用程序更新将包含 从 返回值的 。更新过程在单独的线程中进行,“停止”按钮将停止更新线程。JFrame
JLabel
System.currentTimeMillis
该示例将说明的几个概念:
while
true
boolean
Thread.sleep
请原谅我这个长举的例子:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimeUpdate
{
public void makeGUI()
{
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel l = new JLabel();
class UpdateThread implements Runnable
{
// Boolean used to keep the update loop alive.
boolean running = true;
public void run()
{
// Typically want to have a way to get out of
// a loop. Setting running to false will
// stop the loop.
while (running)
{
try
{
l.setText("Time: " +
System.currentTimeMillis());
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// Once the run method exits, this thread
// will terminate.
}
}
// Start a new time update thread.
final UpdateThread t = new UpdateThread();
new Thread(t).start();
final JButton b = new JButton("Stop");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
t.running = false;
}
});
// Prepare the frame.
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(l, BorderLayout.CENTER);
f.getContentPane().add(b, BorderLayout.SOUTH);
f.setLocation(100, 100);
f.pack();
f.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new TimeUpdate().makeGUI();
}
});
}
}
有关线程化和使用 Swing 的一些资源:
Thread.Sleep可能不是全部答案。对于大多数游戏来说,CPU对于所需的工作量来说太多了。简单地睡一段时间并不是那么有效,因为你可能仍然会消耗太多的资源,或者还不够。您通常希望以某种方式安排工作时间。
如果您考虑一下,屏幕仅以一定的速率更新,通常每秒不到100次。我不熟悉Java API的这种事情,但你想要的是找出显示器的刷新速度,然后在每次刷新之间只更新一次。
此外,您的主循环不需要这样的循环,您可以使用计时器定期调用更新代码。这甚至更有效率。