Java OpenGL-线程在不应该挂起时挂起
为了对线程有一个基本的了解,我一直在学习另一个java游戏开发教程,我已经学习了一些教程,并将它们与我之前学过的openGL编程相结合。除了我想我可能错过了什么,因为在调用Java OpenGL-线程在不应该挂起时挂起,java,multithreading,opengl,lwjgl,Java,Multithreading,Opengl,Lwjgl,为了对线程有一个基本的了解,我一直在学习另一个java游戏开发教程,我已经学习了一些教程,并将它们与我之前学过的openGL编程相结合。除了我想我可能错过了什么,因为在调用engine.stop()(包括thread.join())时,窗口关闭,程序挂起在后台,您必须结束它的进程 这是我的密码: package com.daboom.threadgl; import org.lwjgl.LWJGLException; import org.lwjgl.input.Keyboard; impor
engine.stop()
(包括thread.join()
)时,窗口关闭,程序挂起在后台,您必须结束它的进程
这是我的密码:
package com.daboom.threadgl;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import com.daboom.threadgl.graphics.Camera;
public class EngineMain implements Runnable {
private boolean running;
private Thread thread;
private Camera cam;
/**
* Starts the Dual Threaded System, does not need to be called,
* already called upon application beginning
*/
@Override
public void run() {
initDisplay();
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int updates = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
update();
updates++;
delta--;
}
render();
if (Display.isCloseRequested())
break;
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println(updates + " u/sec " + frames + " f/sec");
Display.setTitle(Game.gameName + " || " + updates + " u/sec " + frames
+ " f/sec ||");
updates = 0;
frames = 0;
}
}
stop();
}
private void update() {
game.update();
}
Game game;
private void render() {
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
cam.useView();
game.render3D();
cam.setProjection2D(Display.getWidth(), Display.getHeight());
game.render2D();
Display.update();
cam.resetTo3D();
}
public EngineMain() {
cam = new Camera();
game = new Game(this, cam);
}
private void initDisplay() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle(Game.gameName);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glClearColor(0, 0, 0, 1);
cam.setProjection3D(63,(float) Display.getWidth() / (float)Display.getHeight(), 0.3f,
1000);
try {
Keyboard.create();
Mouse.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
}
/**
* Starts the Multi-Threading and the Game
*
*/
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
/**
* Safely Stops the program
* Call this to exit the game
*/
public synchronized void stop() {
running = false;
Mouse.destroy();
Keyboard.destroy();
Display.destroy();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
EngineMain main = new EngineMain();
main.start();
}
}
当我使用他的教程时,在没有修改代码的情况下,这个过程会正常结束
我无法用我的生命来识别问题
如果你需要更多的意见,尽管问
编辑:这是修改前的原始代码
package com.thecherno.rain;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.thecherno.rain.graphics.Screen;
import com.thecherno.rain.input.Keyboard;
public class Game extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
public static String title = "Rain";
private Thread thread;
private JFrame frame;
private Keyboard key;
private boolean running = false;
private Screen screen;
private BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer())
.getData();
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
screen = new Screen(width, height);
frame = new JFrame();
key = new Keyboard();
addKeyListener(key);
}
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int updates = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
update();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println(updates + " u/sec " + frames + " f/sec");
frame.setTitle(title + " | " + updates + " u/sec " + frames
+ " f/sec");
updates = 0;
frames = 0;
}
}
stop();
}
int x, y;
public void update() {
key.update();
if (key.up)
y--;
if (key.down)
y++;
if (key.left)
x--;
if (key.right)
x++;
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
screen.clear();
screen.render(x, y);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle(Game.title);
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
package com.thecherno.rain;
导入java.awt.Canvas;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.image.BufferStrategy;
导入java.awt.image.buffereImage;
导入java.awt.image.DataBufferInt;
导入javax.swing.JFrame;
导入com.thecherno.rain.graphics.Screen;
导入com.thecherno.rain.input.Keyboard;
公共类游戏扩展画布实现可运行{
/**
*
*/
私有静态最终长serialVersionUID=1L;
公共静态整数宽度=300;
公共静态内部高度=宽度/16*9;
公共静态int标度=3;
公共静态字符串title=“Rain”;
私有线程;
私有JFrame;
私钥;
私有布尔运行=false;
私人屏幕;
私有缓冲区图像=新的缓冲区图像(宽度、高度、,
BuffereImage.TYPE_INT_RGB);
私有int[]像素=((DataBufferInt)image.getRaster().getDataBuffer())
.getData();
公共游戏(){
尺寸尺寸=新尺寸(宽度*比例,高度*比例);
设置首选大小(大小);
屏幕=新屏幕(宽度、高度);
frame=新的JFrame();
键=新键盘();
addKeyListener(键);
}
公共同步的void start(){
运行=真;
线程=新线程(此“显示”);
thread.start();
}
公共同步无效停止(){
运行=错误;
试一试{
thread.join();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
公开募捐{
long lastTime=System.nanoTime();
长定时器=System.currentTimeMillis();
最终双ns=100000000.0/60.0;
双增量=0;
int帧=0;
int=0;
(跑步时){
long now=System.nanoTime();
增量+=(现在-上次)/ns;
上次=现在;
而(增量>=1){
更新();
更新++;
三角洲--;
}
render();
frames++;
if(System.currentTimeMillis()-计时器>1000){
定时器+=1000;
系统输出打印项次(更新+“u/sec”+帧+“f/sec”);
frame.setTitle(title+“|”+更新+“u/sec”+帧
+“f/sec”);
更新=0;
帧=0;
}
}
停止();
}
int x,y;
公共无效更新(){
key.update();
如果(键向上)
y--;
如果(键向下)
y++;
如果(左键)
x--;
如果(右键)
x++;
}
公共无效呈现(){
BufferStrategy bs=getBufferStrategy();
如果(bs==null){
创新战略(3);
返回;
}
screen.clear();
屏幕渲染(x,y);
对于(int i=0;i
您的修改可能导致一些非守护进程线程启动。您可以在更改前后使用以下方法查看正在运行的线程
private static void dumpThreads() {
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread thread : threadSet) {
System.out.println(String.format("threadName = '%s', daemon = %b",
thread.getName(), thread.isDaemon()));
}
}
private static void dumpThreads(){
Set threadSet=Thread.getAllStackTraces().keySet();
用于(螺纹:螺纹组){
System.out.println(String.format(“threadName='%s',daemon=%b”),
thread.getName(),thread.isDaemon());
}
}
也看到这个:好的,所以我已经弄明白了。。。正如BDL所说,我不能在活动线程中调用join,不幸的是,由于LWJGL的不可饶恕性,它需要重新构造主类 以下是当前代码,供将来参考(供我和其他人参考):
package com.daboom.threadgl;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import com.daboom.threadgl.graphics.Camera;
public class EngineMain implements Runnable {
private boolean running;
private Thread thread;
private Camera cam;
public boolean isLogicThreadRunning = false;
/**
* Starts the Dual Threaded System, does not need to be called, already
*/
@Override
public void run() {
while (running) {
update();
Display.sync(60);
}
}
private void update() {
game.update();
}
Game game;
private void render() {
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
cam.useView();
game.render3D();
cam.setProjection2D(Display.getWidth(), Display.getHeight());
game.render2D();
Display.update();
cam.resetTo3D();
}
public EngineMain() {
cam = new Camera();
game = new Game(this, cam);
}
private void initDisplay() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle(Game.gameName);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glClearColor(0, 0, 0, 1);
cam.setProjection3D(63,
(float) Display.getWidth() / (float) Display.getHeight(), 0.3f,
1000);
}
/**
* Starts the Game engine
*
*/
public synchronized void start() {
running = true;
if (Runtime.getRuntime().availableProcessors() > 1) {
thread = new Thread(this, "Update");
thread.start();
isLogicThreadRunning = true;
}
else
{
isLogicThreadRunning = false;
System.out.println("WARNING: SINGLE CORE SYSTEM DETECTED, FPS LIMITED TO 60");
}
initDisplay();
gameLoop();
}
/**
* Stops the program. Call this to exit the game
*/
public synchronized void stop() {
running = false;
System.out.println(Thread.currentThread().getName());
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// dumpThreads();
}
public void gameLoop() {
while (running) {
if (!isLogicThreadRunning) {
update();
Display.sync(60);
}
render();
if (Display.isCloseRequested())
running = false;
}
}
public static void main(String[] args) {
EngineMain main = new EngineMain();
main.start();
}
}
我花了很长时间才弄明白这一点,我仍然不知道教程中的原始代码是如何工作的,但似乎试图在其中实现LWJGL似乎打破了它,因为openGL上下文是单线程的
当然,如果我正在做一些不被推荐或不正确的事情,请告诉我,因为我是一个业余线程。(事实上,我仍然是openGL的业余爱好者……我需要一台新电脑来获得最佳/新功能,唉……仍然坚持使用3.1)我不是Java专家,但在你的情况下,stop是从线程本身调用的。因此,线程基本上会等待自己停止,这可能不起作用。。我将您的
dumpThreads()
方法放入stop()
函数(就在