如何停止Java while循环占用超过50%的CPU? [英] How can I stop a Java while loop from eating >50% of my CPU?

查看:401
本文介绍了如何停止Java while循环占用超过50%的CPU?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我在一个空程序上进行了测试,仅运行一会儿(true){}就使我的CPU占用了50%以上的内存.我正在开发一个游戏,该游戏使用while循环作为主循环,并且CPU始终处于100.

Okay, I tested this on an empty program, and just having a while(true){} running gave me >50% on my CPU. I have a game I'm working on that uses a while loop as it's main loop, and it's CPU is at 100 all the time.

如何让Java一遍又一遍地重复某件事,而又不会消耗我50%以上的CPU来做重复呢?

How can I get Java to repeat something over and over without eating up >50% of my CPU just to do the repeating?

推荐答案

添加睡眠以使线程在一段时间内处于空闲状态:

Add a sleep to put the thread into idle for some interval:

Thread.sleep

没有睡眠,while循环将消耗所有可用的计算资源. (例如,理论上,单核系统为100%,双核系统为50%,依此类推.)

Without having a sleep, the while loop will consume all the computing resources that is available. (For example, theoretically, 100% in a single core system, or 50% in a dual core, and so on.)

例如,以下内容将大约每50毫秒通过while循环循环一次:

For example, the following will cycle once through a while loop approximately every 50 milliseconds:

while (true)
{
    try
    {
        Thread.sleep(50);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

这应该会大大降低CPU利用率.

This should bring down the CPU utilization quite a bit.

在循环中休眠之后,操作系统还将为其他线程和进程提供足够的系统时间来执行其任务,因此系统也将做出响应.在单核系统和具有不太好的调度程序的操作系统的时代,像这样的循环可能会使系统反应迟钝.

With a sleep in the loop, the operating system will also give enough system time for other threads and processes to do their things, so the system will be responsive as well. Back in the days of single core systems and operating systems with not-so-good schedulers, loops like this could have made the system very unresponsive.

由于出现了在游戏中使用while循环的主题,因此,如果游戏要包含GUI,则游戏循环必须位于单独的线程中,否则GUI本身将无响应.

Since the topic of use of while loops for a game came up, if the game is going to involve a GUI, the game loop must be in a separate thread or else the GUI itself will become unresponsive.

如果该程序将是一个基于控制台的游戏,那么线程化将不再是问题,而是使用事件驱动的图形用户界面,该代码中存在长寿命的循环将使该GUI成为可能.没有反应.

If the program is going to be a console-based game, then threading is not going to be an issue, but with graphical user interfaces which are event-driven, having a long-living loop in the code will make the GUI unresponsive.

线程等是编程中非常棘手的领域,尤其是在入门时,所以我建议在必要时提出另一个问题.

Threading and such are pretty tricky areas of programming, especially when getting started, so I suggest that another question be raised when it becomes necessary.

以下是基于JFrame的Swing应用程序的示例,该应用程序更新了JLabel,该JLabel将包含从System.currentTimeMillis返回的值.更新过程在单独的线程中进行,并且停止"按钮将停止更新线程.

The following is an example of a Swing application based in a JFrame which updates a JLabel that will contain the returned value from System.currentTimeMillis. The updating process takes place in a separate thread, and a "Stop" button will stop the update thread.

该示例将说明一些概念:

Few concepts the example will illustrate:

  • 基于Swing的GUI应用程序,具有单独的线程来更新时间-这将防止GUI线程锁定. (在Ewing中称为EDT或事件调度线程.)
  • 使while循环的循环条件不是true,而是用boolean代替,这将确定是否使循环保持活动状态.
  • Thread.sleep如何纳入实际应用.
  • A Swing-based GUI application with a separate thread to update time -- This will prevent lock up of the GUI thread. (Called the EDT, or event dispatch thread in Swing.)
  • Having the while loop with a loop condition that is not true, but substituted with a boolean which will determine whether to keep the loop alive.
  • How Thread.sleep factors into an actual application.

请原谅我的例子:

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的一些资源:

Some resources about threading and using Swing:

  • Threads and Swing
  • Lesson: Concurrency

这篇关于如何停止Java while循环占用超过50%的CPU?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆