Swing 中的并发与 While 循环
Concurrency in Swing with While Loops
我一直在阅读 Java Swing 中的并发性,但找不到适合我的情况的答案。
目标: 让我的 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 class 在后台执行我的 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
来防止线程之间可能出现脏 read/writes 并使 Thread
成为守护线程,因此应用程序可以关闭并且线程不会阻止 JVM 终止。
就我个人而言,我倾向于使用 SwingWorker
,因为它提供的功能允许您简单地将更新同步回 UI
查看 Concurrency in Swing and Worker Threads and SwingWorker 了解更多详情
我一直在阅读 Java Swing 中的并发性,但找不到适合我的情况的答案。
目标: 让我的 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 class 在后台执行我的 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
来防止线程之间可能出现脏 read/writes 并使 Thread
成为守护线程,因此应用程序可以关闭并且线程不会阻止 JVM 终止。
就我个人而言,我倾向于使用 SwingWorker
,因为它提供的功能允许您简单地将更新同步回 UI
查看 Concurrency in Swing and Worker Threads and SwingWorker 了解更多详情