好吧,我在一个空程序上测试了这个,只是运行一段时间(真实){}给了我50%的CPU.我有一个我正在使用的游戏,它使用while循环作为它的主循环,并且它的CPU始终为100.
我怎样才能让Java一遍又一遍地重复一些事情而不吃掉超过50%的CPU来做重复?
添加一个睡眠以使线程空闲一段时间:
Thread.sleep
没有睡眠,while循环将消耗所有可用的计算资源.(例如,理论上,单核系统中为100%,双核中为50%,依此类推.)
例如,以下内容将while
大约每50毫秒循环一次循环:
while (true) { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } }
这应该会降低CPU的利用率.
在循环中休眠时,操作系统还将为其他线程和进程提供足够的系统时间来执行其操作,因此系统也将响应.在具有不太好的调度程序的单核系统和操作系统的时代,像这样的循环可能使系统非常无响应.
由于while
游戏循环的使用主题出现了,如果游戏涉及GUI,游戏循环必须在一个单独的线程中,否则GUI本身将变得无响应.
如果该程序将成为基于控制台的游戏,那么线程不会成为问题,但是对于事件驱动的图形用户界面,在代码中具有长期循环将使GUI无响应.
线程等等都是非常棘手的编程领域,特别是在入门时,所以我建议在必要时提出另一个问题.
以下是基于a的Swing应用程序的示例,该应用程序JFrame
更新JLabel
将包含返回值的应用程序System.currentTimeMillis
.更新过程在一个单独的线程中进行,"停止"按钮将停止更新线程.
该示例的几个概念将说明:
基于Swing的GUI应用程序,具有单独的线程来更新时间 - 这将防止GUI线程的锁定.(在Swing中称为EDT或事件派发线程.)
具有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的一些资源:
线程和Swing
课程:并发
Thread.Sleep可能不是完整的答案.对于大多数游戏来说,CPU所需的工作量太多了.简单地睡一段时间并不是那么有效,因为你可能仍然会烧掉太多的资源,或者说不够.您通常希望以某种方式计算您的工作时间.
如果你考虑一下,屏幕只会以一定的速率更新,通常每秒少于100次.我对这种事情并不熟悉Java api,但你想要的是找出显示器的刷新速度,然后在每次刷新之间只更新一次.
此外,您不需要像主循环那样的循环,您可以使用计时器定期调用更新代码.这甚至更有效.
你确实在忙着等待,这意味着你要经常检查一个或多个条件,直到它们成立为止.
Thread.sleep()
不是解决方案.使用wait()
和notify()
方法可以让你完成你正在尝试的,但效率更高.基本上,这种机制允许线程在对象上休眠,直到对象决定发生了什么并且想要唤醒在其上休眠的所有线程.
代码exmaples可以在这里和这里找到.
这应该是你的解决方案,而不是用计时器隐藏你的忙等待.
虽然是的,你可以做一个
Thread.sleep(50)
像接受的答案建议,你也可以打电话
Thread.sleep(0)
这将告诉处理器进行上下文切换.等待执行的其他线程(如GUI绘图线程)将被执行,机器将停止感觉缓慢.
sleep(0)方式也会最大化操作系统给你的应用程序的时间,因为线程会立即回到处理器的队列中(而不是等待50ms才这样做)所以如果没有其他线程在等待,你的线程将继续被执行.
通常在游戏循环中你会暂停一下......例如:http://developers.sun.com/mobility/midp/articles/game/