java - Swing 中的并发与 While 循环

标签 java swing concurrency swingworker event-dispatch-thread

我一直在阅读 Swing 中的 Java 并发性,但找不到适合我的情况的答案。

目标:让我的 swing 应用程序同时运行 while 循环直到程序/应用程序退出。

问题:程序卡住(正如我事先预期的那样)并且无法使用。

尝试的解决方案:我试图在另一个线程上启动 while 循环,启动了它,仍然没有。

代码:

package stakeme;

import java.io.IOException;

import javax.swing.SwingUtilities;

public class StakeMeServer {

    private static ServerSocket socket;

    public static Thread t;


    public static void main(String[] args) throws IOException {


        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ConsoleGUI("Server", 800, 400, false);
            }

        });

        Thread t = new Thread(() -> {
            System.out.println("1");
            while (online) {
                System.out.println("2");
            }
        });
        t.setName("GameServer");
        t.start();
    }

}



更新:通过使用 SwingWorker 类在后台执行我的 while 循环,我几乎能够完成我需要做的事情。

代码:

package stakeme;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class StakeMeServer {

    private static AtomicBoolean online = new AtomicBoolean(false);

    public static GameServerLoop gsl = new GameServerLoop();


    public static void main(String[] args) throws IOException {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }

                new ConsoleGUI("Server", 800, 400, false);

            }

        });

        //this should always be running during the life of the program
        gsl.execute();

    }

    static class GameServerLoop extends SwingWorker<Void, Void> {

        @Override
        protected Void doInBackground() {
            System.out.println("1");
            while (true) {
                while (online.get()) {
                    System.out.println("2");
                }
            }
        }

    }

}



一切正常,出了故障。使用 System.out.println() 方法以处理速度(while 循环)运行此程序将使程序有些无响应。单击停止按钮将起作用。最终。由于大量的 System.out.println() 调用,似乎一切都已备份。

最佳答案

所以你不完整的例子留下了很多问题没有答案,基本上,像这样..

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class StakeMeServer {

    private ServerSocket socket;
    private Thread t;
    private AtomicBoolean online = new AtomicBoolean(false);

    public static void main(String[] args) throws IOException {
        new StakeMeServer();
    }

    public StakeMeServer() {

        SwingUtilities.invokeLater(new Runnable() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new TestPane());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });

        open();

        Thread t = new Thread(() -> {
            System.out.println("1");
            while (online.get()) {
                System.out.println("2");
            }
        });
        t.setDaemon(true);
        t.setName("GameServer");
        t.start();
    }

    public void open() {
        System.out.println("Starting Server...");
        online.set(true);
        System.out.println("Server Online");
    }

    public void close() {
        System.out.println("Stopping Server...");
        online.set(false);
        System.out.println("Server Offline");
    }

    public class TestPane extends JPanel {

        private int x = 0;
        private int delta = 4;

        private JLabel state;

        public TestPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    x += delta;
                    if (x + 10 > getWidth()) {
                        x = getWidth() - 10;
                        delta *= -1;
                    } else if (x < 0) {
                        x = 0;
                        delta *= -1;
                    }
                    state.setText(Boolean.toString(online.get()));
                    repaint();
                }
            });
            timer.start();

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            state = new JLabel(Boolean.toString(online.get()));
            add(state, gbc);

            JButton btn = new JButton("Stop");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    close();
                }
            });
            add(btn, gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.fillOval(x, (getHeight() / 2) - 5, 10, 10);
            g2d.dispose();
        }

    }

}

工作得很好。

我使用 AtomicBoolean 而不是 boolean 来防止线程之间可能的脏读/写,并使 Thread 成为守护线程,所以应用程序可以关闭,线程不会阻止 JVM 终止。

就个人而言,我倾向于使用 SwingWorker,因为它提供的功能允许您简单地将更新同步回 UI

看看Concurrency in SwingWorker Threads and SwingWorker了解更多详情

关于java - Swing 中的并发与 While 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35449575/

相关文章:

java - 从另一个 Jenkins 构建中查找 Artifactory URL

java - 文本区域未显示在选项卡式面板中

c - 缩短线程安全(不平衡)二叉树中的关键部分

multithreading - Rust 是否有内置或规范的方式来处理 ‘publish’ 状态?

java - Servlet 解析 JSON 时出现 ClassNotFoundException

java - 简单Java服务中的并发问题

java - 如何在 Java 服务器中可靠且高效地读取来自 Apple Push Notifications Server 的所有错误响应?

带有对象填充的 Java JTable vector

java - JFrame 类型的 createGUI() 方法未定义

c++ - condition_variable 并不总是有效