Подтвердить что ты не робот

Как я могу остановить цикл Java while от использования> 50% моего процессора?

Хорошо, я тестировал это на пустой программе, и просто имея некоторое время (правда) {}, я дал мне > 50% на моем процессоре. У меня есть игра, над которой я работаю, которая использует цикл while в качестве основного цикла, а его процессор все равно 100.

Как я могу заставить Java повторять что-то снова и снова, не съедая > 50% моего процессора, просто чтобы повторить?

4b9b3361

Ответ 1

Добавьте спать, чтобы поместить поток в режим ожидания на некоторый интервал:

Thread.sleep

Не имея сна, цикл while будет потреблять все доступные вычислительные ресурсы. (Например, теоретически, 100% в одноядерной системе или 50% в двухъядерном ядре и т.д.)

Например, следующее цикл будет циклически повторяться через цикл while примерно каждые 50 миллисекунд:

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

Это должно сильно снизить загрузку процессора.

С сон в цикле операционная система также даст достаточно системного времени для других потоков и процессов для выполнения своих задач, поэтому система также будет реагировать. Еще в дни одноядерных систем и операционных систем с не очень хорошими планировщиками такие петли могли бы сделать систему очень невосприимчивой.


Поскольку тема использования циклов while для игры подошла, если игра будет включать GUI, игровой цикл должен быть в отдельном потоке, иначе сам GUI перестанет отвечать.

Если программа будет консольной игрой, то потоковая передача не будет проблемой, но с графическими пользовательскими интерфейсами, которые управляются событиями, имея длинный цикл в коде, сделает GUI отвечать на запросы.

Threading и такие довольно сложные области программирования, особенно при запуске, поэтому я предлагаю, чтобы возникли вопросы, когда это становится необходимым.

Ниже приведен пример приложения Swing, основанного на JFrame, который обновляет JLabel, который будет содержать возвращаемое значение из System.currentTimeMillis. Процесс обновления происходит в отдельном потоке, а кнопка "Стоп" останавливает поток обновлений.

Несколько понятий, которые иллюстрирует пример:

  • Приложение GUI на основе Swing с отдельным потоком для обновления времени - это предотвратит блокировку потока GUI. (Вызывается EDT или поток отправки событий в Swing.)
  • Наличие цикла 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:

Ответ 2

Thread.Sleep может быть не полным ответом. Для большинства игр там слишком много CPU для необходимого объема работы. Просто спать в течение определенного времени не так эффективно, так как вы, скорее всего, либо будете сжигать слишком много ресурсов, либо недостаточно. Вы, как правило, хотите, чтобы ваша работа была каким-то образом.

Если вы думаете об этом, экран обновляется с определенной скоростью, обычно менее 100 раз в секунду. Я не знаком с Java api для такого рода вещей, но вы хотите узнать скорость обновления монитора и затем обновлять только один раз между каждым обновлением.

Кроме того, вам не нужен такой цикл для вашего основного цикла, вы можете использовать таймеры для вызова своего кода обновления с регулярным интервалом. Это еще более эффективно.

Ответ 3

Вы действительно заняты ожиданиями, то есть вы постоянно измельчаете свой процессор при проверке одного или нескольких условий, пока они не верны.

Thread.sleep() не решение. Использование методов wait() и notify() позволяет вам делать именно то, что вы пытаетесь, но гораздо эффективнее. В принципе, этот механизм позволяет потоку спать на объекте, пока объект не решит, что что-то произошло, и хочет разбудить на нем все нити.

Сценарии кода можно найти здесь и здесь.

Этот должен быть вашим решением, а не скрывать ожидание с помощью таймера.

Ответ 5

Пока да, вы можете сделать

Thread.sleep(50)

как и принятый ответ, вы также можете позвонить

Thread.sleep(0) 

Это будет означать, что процессор выполняет контекстный переключатель. Затем будут выполнены другие потоки, ожидающие выполнения (например, поток чертежа графического интерфейса), и машина перестанет чувствовать себя медленной.

Режим sleep (0) также максимизирует время, предоставляемое ОС для вашего приложения, потому что поток немедленно возвращается в очередь процессора (вместо ожидания до 50 мс до этого), поэтому, если нет другого потока, в котором вы ожидаете, вы поток будет продолжать выполняться.

Ответ 6

Кажется, что ваш поток оживлен. То есть он попадает в цикл, в котором он ничего не делает. В такой ситуации он будет переваривать много циклов процессора без эффекта.

Как упоминалось другими, ответ Thread.sleep.

Ответ 8

Как о планировщике на основе Quartz- Spring, который продолжает выполнять работу снова и снова с повторением.

Ответ 9

Если есть прерывание, это, вероятно, по какой-то причине. Лучший способ справиться с этим -

try {
    while (true) {
        Thread.sleep(50);
    }
} catch (InterruptException e) {
    Thread.currentThread().interrupt();
}

Однако этот цикл ничего не делает, поэтому я предлагаю вам просто удалить его. Довольно редко вы хотите заняться ожиданием условия (в этом случае класс условий является лучшим выбором), как правило, вы можете преобразовать одно и то же поведение, не требуя цикла вообще.