如何阻止Java while循环进食>;50%的CPU?
好的,我在一个空的程序上测试了这个,仅仅运行一段时间(真的){}就让我的CPU占用了>50%。我有一个我正在开发的游戏,它使用while循环作为主循环,它的CPU一直在100如何阻止Java while循环进食>;50%的CPU?,java,loops,cpu-usage,Java,Loops,Cpu Usage,好的,我在一个空的程序上测试了这个,仅仅运行一段时间(真的){}就让我的CPU占用了>50%。我有一个我正在开发的游戏,它使用while循环作为主循环,它的CPU一直在100 如何让Java一遍又一遍地重复某件事情,而不只是为了重复而占用超过50%的CPU?添加睡眠以使线程在一段时间内处于空闲状态: 如果没有睡眠,while循环将消耗所有可用的计算资源。(例如,理论上,单核系统为100%,双核系统为50%,依此类推。) 例如,以下内容将在循环中循环一次,而循环大约每50毫秒循环一次: whil
如何让Java一遍又一遍地重复某件事情,而不只是为了重复而占用超过50%的CPU?添加睡眠以使线程在一段时间内处于空闲状态: 如果没有睡眠,while循环将消耗所有可用的计算资源。(例如,理论上,单核系统为100%,双核系统为50%,依此类推。) 例如,以下内容将在
循环中循环一次,而循环大约每50毫秒循环一次:
while (true)
{
try
{
Thread.sleep(50);
}
catch (Exception e)
{
e.printStackTrace();
}
}
这将大大降低CPU利用率
在循环中睡眠的情况下,操作系统还将为其他线程和进程提供足够的系统时间来完成它们的工作,因此系统也将具有响应性。在单核系统和具有不太好的调度器的操作系统的时代,像这样的循环可能会使系统非常无响应
由于出现了在游戏中使用而循环的主题,如果游戏将涉及GUI,则游戏循环必须位于单独的线程中,否则GUI本身将变得无响应
如果程序将是基于控制台的游戏,那么线程将不是问题,但是对于事件驱动的图形用户界面,在代码中有一个长期的循环将使GUI没有响应
线程等是编程中相当棘手的领域,特别是在刚开始的时候,因此我建议在必要时提出另一个问题
下面是一个基于JFrame
的Swing应用程序示例,它更新了JLabel
,该标签将包含来自System.currentTimeMillis
的返回值。更新过程在单独的线程中进行,“停止”按钮将停止更新线程
本例将说明几个概念:
- 一个基于Swing的GUI应用程序,有一个单独的线程来更新时间——这将防止GUI线程被锁定。(称为EDT,或Swing中的事件调度线程。)
- 使
while
循环的循环条件不是true
,而是用布尔值
替换,这将决定是否保持循环活动
- 如何
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的一些资源:
通常在游戏循环中,你会暂停一会儿。。。例如:您的线程似乎正在忙着等待。也就是说,它被困在一个什么都不做的循环中。在这种情况下,它会占用大量cpu周期而没有效果
正如其他人提到的,Thread.sleep是答案。Thread.sleep可能不是全部答案。对于大多数游戏来说,CPU对于所需的工作量来说太多了。简单地睡上一段时间并不是很有效率,因为你可能会消耗太多的资源,或者是不够。您通常希望以某种方式确定工作时间
仔细想想,屏幕只会以一定的速度更新,通常每秒更新不到100次。我不熟悉这类东西的JavaAPI,但您需要了解监视器的刷新速度,然后在每次刷新之间只更新一次
此外,主循环不需要这样的循环,您可以使用计时器定期调用更新代码。这甚至更有效。,但想法保持不变:尝试使用观察者模式,而不是wile(true)
您确实在忙着等待,这意味着您在不断地检查一个或多个条件,直到它们为真
Thread.sleep()
不是解决方案。使用wait()
和notify()
方法可以让您只做您正在尝试的事情,但效率更高。基本上,这种机制允许线程在对象上休眠,直到对象确定发生了什么事情并希望唤醒所有在其上休眠的线程
可以找到代码exmaple并
这应该是您的解决方案,而不是用计时器隐藏繁忙的等待。一个基于Quartz Spring的调度器如何,它可以在重复的时间间隔内一遍又一遍地执行工作。是的,您可以执行
Thread.sleep(50)
正如公认的答案所建议的那样,你也可以打电话
Thread.sleep(0)
这将告诉处理器进行上下文切换。等待执行的其他线程(如GUI绘图线程)将被执行,机器将停止感觉缓慢
睡眠(0)方式还将最大限度地延长操作系统给应用程序的时间,因为线程将立即返回处理器队列(而不是等待50毫秒),因此如果没有其他线程在等待,您的线程将继续执行。如果出现中断,可能是由于某种原因。更好的处理方法是
try {
while (true) {
Thread.sleep(50);
}
} catch (InterruptException e) {
Thread.currentThread().interrupt();
}
但是这个循环没有任何作用,所以我建议您删除它。很少有人想忙着等待条件(在这种情况下,条件类是更好的选择),通常可以将相同的行为转换为根本不需要循环。这是我的第一个想法,但你比我先想到了:)请注意,轮询(睡眠一段时间)对于示例代码来说是非常好的(使用当前时间更新文本标签)。但对于处理复杂的事件队列,通常最好阻止事件队列中是否存在条目(使用监视器)线程。睡眠(0)也会强制上下文切换