java - 当 while(true) 在线程中循环时 JFrame 卡住

标签 java multithreading parallel-processing freeze jinternalframe

我简化了我的代码与大家分享。目前有3个类(class)。 JFrame、JInternalFrame 和线程。 JFrame 创建 JInternalFrame,JInternalFrame 创建线程。我的线程中的构造函数需要一个 JInternalFrame 的实例来处理它的按钮。 因此,在创建 InternalFrame 的界面后,我创建并启动线程。不幸的是,整个 JFrame 卡住了,代码将完全保留在线程中。我已经尝试摆脱线程中的 while(true) 循环。然后 JFrame 仅在我的 sleep 功能需要的时间内卡住。

长话短说:如何让我的线程真正并行运行?我的主代码无需等待线程中的任何 sleep 时间或类似的东西。

这是我的 3 门类(class)。对于任何愚蠢的菜鸟错误,提前表示歉意。我还在学习中。

JFrame

package nachgestellt;

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class Langtons extends JFrame implements ActionListener {
    private JDesktopPane desk;
    private JPanel panelButtons;
    JMenuBar jmb;
    JMenu file;
    JMenuItem open, exit;
    JSlider slider;
    int xInt, yInt;

    Random randomGenerator = new Random();

    JLabel xLabel, yLabel, speed, test;
    JButton start, stop, addAnt;
    JTextField xField, yField;

    public Langtons() {
        //Desktop
        desk = new JDesktopPane();
        getContentPane().add(desk, BorderLayout.CENTER);

        xField = new JTextField();
        yField = new JTextField();

        start = new JButton("Fenster erstellen");

        panelButtons = new JPanel();
        panelButtons.setLayout(new GridLayout());
        ;

        panelButtons.add(start);
        panelButtons.add(xField);
        panelButtons.add(yField);

        start.addActionListener(this);
        add(panelButtons, BorderLayout.NORTH);
        setSize(new Dimension(1100, 900));
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Fenster erstellen")) {
            xInt = Integer.parseInt(xField.getText());
            yInt = Integer.parseInt(yField.getText());
            addChild(new kind(this, xInt, yInt), this.getSize().width, this.getSize().height);
        }
    }


    public void addChild(JInternalFrame kind, int x, int y) {
        kind.setSize(370, 370);
        kind.setLocation(randomGenerator.nextInt(x - kind.getSize().height), randomGenerator.nextInt(y - kind.getSize().height - 100));
        kind.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
        desk.add(kind);
        kind.setBackground(Color.blue);
        kind.setVisible(true);

    }

    public static void main(String[] args) {
        new Langtons();
    }

}

JInternalFrame

package nachgestellt;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.ArrayList;

import javax.swing.*;


public class kind extends JInternalFrame {

    Langtons hFenster;
    static int nr = 0;

    JPanel panelButtonsKind;

    ArrayList<JButton> jbArray = new ArrayList<JButton>();

    JPanel panelSpielfeld;

    int posAmeise, aktuellesIcon;

    public kind(Langtons la, int x, int y) {
        super("Kind " + (++nr), true, true, true, true);
        hFenster = la;

        panelSpielfeld = new JPanel();

        panelSpielfeld.setLayout(new GridLayout(y, x));

        jbArray.add(new JButton());

        for (int i = 1; i <= (x * y); i++) {
            jbArray.add(new JButton(Integer.toString(i)));
            panelSpielfeld.add(jbArray.get(i));
            jbArray.get(i).setBackground(Color.WHITE);
        }

        jbArray.get(((x / 2) * y) - y / 2).setBackground(Color.GREEN);

        posAmeise = (((x / 2) * y) - y / 2);

        setLayout(new BorderLayout());

        panelButtonsKind = new JPanel();
        panelButtonsKind.setLayout(new GridLayout(1, 3));

        add(panelButtonsKind, BorderLayout.NORTH);
        add(panelSpielfeld, BorderLayout.CENTER);
        setVisible(true);

        this.repaint();
        thread a = new thread(this);
        a.start();
        System.out.println("Test Message After Creation and Start of Thread");
    }

    public void changeColor() {
        if (jbArray.get(posAmeise).getBackground().equals(Color.GREEN))
            jbArray.get(posAmeise).setBackground(Color.WHITE);
        else
            jbArray.get(posAmeise).setBackground(Color.GREEN);
    }
}

话题

package nachgestellt;

import java.awt.Color;

public class thread extends Thread {

    kind k;

    public thread(kind kk) {
        this.k = kk;
        run();
    }

    public void run() {
        super.run();

        while (true) {
            if (k.jbArray.get(k.posAmeise).getBackground().equals(Color.GREEN)) {
                try {
                    sleep(1000);

                    k.changeColor();
                    System.out.println("Test Message Thread!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            } else if (k.jbArray.get(k.posAmeise).getBackground()
                    .equals(Color.WHITE)) {
                try {
                    sleep(1000);
                    k.changeColor();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最佳答案

Swing 是单线程的并且不是线程安全的,您永远不应该在事件调度线程中执行任何可能会阻塞它或长时间运行的操作。同样,您永远不应该尝试从 EDT 外部更新 UI。

参见Concurrency in Swing了解更多详情。

Thread#run 将简单地在当前线程的上下文中调用 Threadrun 方法,这并不是特别有用,您应该使用Thread#start

但是,话虽如此,在您的情况下,您应该使用 Swing Timer 而不是 Thread。计时器将按照指定的延迟间隔设置对注册的 ActionListener 的回调,该回调在 EDT 的上下文中执行,从而可以安全地从内部更新 UI。

参见How to use Swing Timers了解更多详情

关于java - 当 while(true) 在线程中循环时 JFrame 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30088887/

相关文章:

java - 从 map 内的列表中查找对象

java - 上传 PNG 和 GIF 文件时出现 JAI 错误

C - GTK3 和线程

python - 在 python 中使用多处理并行化递归代码

c - MPI中3D过程分解中交换2D光晕的子数组数据类型的数量

java - Windows 10 通知中的空白图标

multithreading - 用整数数学分割文件

Python 线程不运行

python - 在 python 中使用 joblib 进行并行处理时,对象属性似乎没有变化

java - 如何在 Spring mvc 中使用新的 httpstatus 代码进行响应