@General-purpose

Как заставить программу использовать CPU только по мере небходимости?

Пытаюсь грамотно реализовать тестовую программу на Java, Windows 7.
Проблема: когда программа запущена, её процесс стабильно использует определённый % CPU, даже если это пустой цикл.
61b3c35eba3b1641168586.png
Это нехорошо, некрасиво, неправильно.
Подскажите как это исправить, дайте код или что-нибудь почитать по теме.

Я так понимаю: в любой программе, если это не одноразовый скрипт, есть по крайней мере один цикл. Но у меня что с пустым, что с полным циклом процессор грузится на 8%. А вот, к примеру, калькулятор виндовый не создаёт видимой нагрузки вообще, однако реагирует на действия пользователя. Как он, например, узнаёт, нажата ли кнопка? Для этого надо выполнять цикл как можно чаще, но нагрузки на процессор почти нет. Мистика какая-то.

Вот конкретный код, Hello World LWJGL
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class HelloWorld {

	// The window handle
	private long window;

	public void run() {
		System.out.println("Hello LWJGL " + Version.getVersion() + "!");

		init();
		loop();

		// Free the window callbacks and destroy the window
		glfwFreeCallbacks(window);
		glfwDestroyWindow(window);

		// Terminate GLFW and free the error callback
		glfwTerminate();
		glfwSetErrorCallback(null).free();
	}

	private void init() {
		// Setup an error callback. The default implementation
		// will print the error message in System.err.
		GLFWErrorCallback.createPrint(System.err).set();

		// Initialize GLFW. Most GLFW functions will not work before doing this.
		if ( !glfwInit() )
			throw new IllegalStateException("Unable to initialize GLFW");

		// Configure GLFW
		glfwDefaultWindowHints(); // optional, the current window hints are already the default
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

		// Create the window
		window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
		if ( window == NULL )
			throw new RuntimeException("Failed to create the GLFW window");

		// Setup a key callback. It will be called every time a key is pressed, repeated or released.
		glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
			if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
				glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
		});

		// Get the thread stack and push a new frame
		try ( MemoryStack stack = stackPush() ) {
			IntBuffer pWidth = stack.mallocInt(1); // int*
			IntBuffer pHeight = stack.mallocInt(1); // int*

			// Get the window size passed to glfwCreateWindow
			glfwGetWindowSize(window, pWidth, pHeight);

			// Get the resolution of the primary monitor
			GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

			// Center the window
			glfwSetWindowPos(
				window,
				(vidmode.width() - pWidth.get(0)) / 2,
				(vidmode.height() - pHeight.get(0)) / 2
			);
		} // the stack frame is popped automatically

		// Make the OpenGL context current
		glfwMakeContextCurrent(window);
		// Enable v-sync
		glfwSwapInterval(1);

		// Make the window visible
		glfwShowWindow(window);
	}

	private void loop() {
		// This line is critical for LWJGL's interoperation with GLFW's
		// OpenGL context, or any context that is managed externally.
		// LWJGL detects the context that is current in the current thread,
		// creates the GLCapabilities instance and makes the OpenGL
		// bindings available for use.
		GL.createCapabilities();

		// Set the clear color
		glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

		// Run the rendering loop until the user has attempted to close
		// the window or has pressed the ESCAPE key.
		while ( !glfwWindowShouldClose(window) ) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

			glfwSwapBuffers(window); // swap the color buffers

			// Poll for window events. The key callback above will only be
			// invoked during this call.
			glfwPollEvents();
		}
	}

	public static void main(String[] args) {
		new HelloWorld().run();
	}

}

При отпускании ESCAPE процесс завершается.
  • Вопрос задан
  • 302 просмотра
Решения вопроса 2
hint000
@hint000
у админа три руки
Как он, например, узнаёт, нажата ли кнопка? Для этого надо выполнять цикл как можно чаще
Как вы узнаёте утром, что надо просыпаться и идти на работу или в школу? Для этого надо всю ночь смотреть на часы как можно чаще. :)
А можно просто "сказать" будильнику (или родственникам), чтобы разбудили в нужное время. Вот так и программа доверяет операционной системе "разбудить" её, когда кто-то нажмёт на кнопку. А пока никто не нажал, программа спит и не тратит ресурсы.
Операционная система в любом случае знает обо всех нажатиях кнопок и обо всех движениях мыши, она решает, какой программе передать эти нажатия или движения, т.е. какую программу нужно разбудить сейчас. Как только программа обработает событие, она снова уснёт, если больше нечего обрабатывать.
Ответ написан
Комментировать
@General-purpose Автор вопроса
Нашол, нужно использовать glfwWaitEvents(); и всего делов. И вынести это дело в отдельный поток. Абсолютно гениальная система.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Ну убери этот пустой цикл.
С точки зрения компьютера - пустой цикл тоже цикл, и его надо ответственно выполнять.
Это нехорошо, некрасиво, неправильно.

Это данность.

Если расскажешь, зачем тебе пустой цикл - мб кто-то подскажет, как его исправить.
Ответ написан
SagePtr
@SagePtr
Еда - это святое
Самый простой вариант - в конце каждой итерации цикла засыпать на несколько миллисекунд, если программе нечего делать. Или ожидать до наступления какого-нибудь события (к примеру, если у вас сокет, ожидающий входящие подключения).
Ответ написан
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
почитай про профилирование кода, в idea/eclipse помнится был встроенный профайлер
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы