Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java OpenGL-线程在不应该挂起时挂起_Java_Multithreading_Opengl_Lwjgl - Fatal编程技术网

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

为了对线程有一个基本的了解,我一直在学习另一个java游戏开发教程,我已经学习了一些教程,并将它们与我之前学过的openGL编程相结合。除了我想我可能错过了什么,因为在调用
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()
函数(就在之前)