【问题标题】:Is it possible to have infinite loop Thread and JFrame in Java?Java中是否可以有无限循环Thread和JFrame?
【发布时间】:2018-03-05 00:20:30
【问题描述】:

我正在尝试创建一些小游戏,其中在一个线程中运行一个无限循环,该循环将执行引擎工作,而在 JFrame 中将是屏幕上输出的所有内容。

但是我面临一个我无法解决的大问题,并且在互联网上也找不到任何答案。当我在线程中的无限循环中没有立即输出到控制台时,似乎那个线程(在引擎类中)被程序杀死,只剩下 JFrame。但是当在无限循环中有一些输出到控制台时,线程(在引擎类中)完全按预期工作,这让我发疯:(

主类:

package ccarsimulator;

import javax.swing.SwingUtilities;

public class CCarSimulator {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Window window = new Window("CCarsimulator");
        });
    }        
}

窗口类:

package ccarsimulator;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Window extends JFrame{
    Engine oEngine = new Engine(this);


    JLabel LabelOutput = new JLabel();

    JPanel PanelCanvas = new JPanel();

    JLabel LabelSpeed;
    JLabel LabelRPM;
    JLabel LabelGearSet;
    JLabel LabelTotalTime;
    JLabel LabelFPS;
    JLabel LabelCPS;

    public Window(String WindowTitle){
        super(WindowTitle);

        this.addKeyListener(new KeyListener(){
            @Override
            public void keyTyped(KeyEvent e) {}
            @Override
            public void keyPressed(KeyEvent oKey) {
                System.out.println("Key Pressed");
                oEngine.bKeyPressed[oKey.getKeyCode()] = true;
            }
            @Override
            public void keyReleased(KeyEvent oKey) {
                oEngine.bKeyPressed[oKey.getKeyCode()] = false;
            }
        });
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent oEvent){
                System.out.println("Closing a Window");
                oEngine.bStopEngine = true;
            }
        });

        this.add(PanelCanvas);
        PanelCanvas.add(LabelOutput);
        LabelOutput.setText("Test");

        this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setFocusable(true);
    }
}

引擎类:

package ccarsimulator;

import java.awt.event.KeyEvent;

public class Engine extends Thread{
    Thread thisSelf = this;
    public boolean bStopEngine = false;
    public Window oWindow;

    public boolean []bKeyPressed = new boolean[KeyEvent.CHAR_UNDEFINED + 1];
    public boolean []bKeyReleased = new boolean[KeyEvent.CHAR_UNDEFINED + 1];

    public Engine(Window oWindow){
        this.oWindow = oWindow;
        thisSelf.start();
    }

    @Override
    public void run(){
        System.out.println("Waiting for window");
        //while(!oWindow.isVisible() && !bStopEngine);
        System.out.println("Engine is up and Running");
        while(!bStopEngine){
            //
            //---------------------------------------
            //Add some output to console to make this loop working...
            //---------------------------------------
            //
            if(bKeyPressed[KeyEvent.VK_ESCAPE]){
                System.out.println("Pressed Escape");
            }
        }
        System.out.println("Engine was disabled");
    }
}

在引擎的类线程无限循环中没有输出到控制台的结果是

Waiting for window
Engine is up and Running
Key Pressed
Key Pressed
Key Pressed
Key Pressed
Closing a Window

一些输出的结果是:

Waiting for window
Engine is up and Running
Some debug
Some debug
...
...
Some debug
Closing a Window
Some debug
Some debug
Engine was disabled

【问题讨论】:

  • 各位,请不要投票给这个帖子,只是解释我做错了什么......或者解释为什么你不给这个帖子投票......因为这对你来说不公平

标签: java multithreading loops jframe infinite


【解决方案1】:

好的,我的 Java Guru 朋友帮我解决了这一切。 并且还回答了我的问题,为什么在我发布这个问题时我仍然觉得不公平,因为我无法清楚地描述它,如果我这样做了,我会在不问的情况下找到我的问题的答案。

问题是我必须在变量上添加 volatile 关键字,这些变量由两个线程(我的引擎线程和 Swing 线程)处理。

没有关键字volatile 我正在经历我的 Swing 线程正在更改 RAM 内存中的这两个引擎线程(bStopEnginebKeyPressed)变量,而这两个引擎线程的变量在 CPU 缓存内存中,所以引擎线程不能知道发生了什么变化,因为这两个变量没有在正确的地方发生变化。

还帮助我理解了为什么我的代码只使用 volatile 设置这两个变量之一。这是因为默认情况下 Java 应该将大约 4KB 的内存页面块加载到 CPU 内存中。因此,如果运气好的话,我的 volatile 变量与 Swing Thread 使用的另一个变量一起进入此页面,而没有使用 volatile 关键字,那么该页面仍设置为线程同步,并且仍将我的变量与 Swing 线程同步,这就是它仍然有效的原因。

只是告诉将来帮助其他人摆脱对类似问题的困惑,或者在我将来再次忘记这一切时为我自己;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 2022-12-20
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多