您的代码当前存在的问题:
- 你正在创建一个Swing GUI的并运行它 关闭 Swing事件分派线程或EDT的。GUI应该在事件线程 上 启动 , 以便确保所有Swing代码都可以在单个线程上运行。
- 您有一个长时间运行的while循环,它正在进行Swing突变调用,从而更新了JButton的状态。如果此代码在Swing事件线程上运行,它将阻止/冻结GUI。应该在不是EDT的后台线程中显式调用此块,并且应按照“ Swing:并发”教程中的内容,将所有Swing调用排队到事件线程中。
- 您在不同的线程中使用了一个非易失性布尔值,可能会导致变量在应更改时未被更改
- 您似乎立即关闭了流,从而阻止了关注点之间的充分沟通。
正在研究更干净的示例…
例如:
import java.awt.Dimension;import java.awt.event.ActionEvent;import java.io.IOException;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;import java.util.Scanner;import javax.swing.*;public class SimpleServerClient { private static final int PORT = 9001; public static void main(String[] args) { SwingUtilities.invokeLater(() -> { try { SimpleServer server = new SimpleServer(PORT, "Server", false); SimpleClient client = new SimpleClient(PORT, "Client", true); server.createGui(); client.createGui(); } catch (IOException e) { e.printStackTrace(); } }); }}interface SimpleGui { void sendLine(String nextLine);}// background thread handles listening to the Scanner // which scans a Socket's InputStreamclass MyWorker extends SwingWorker<Void, Void> { public static final String LINE = "line"; private Scanner inputScanner; private SimpleGui gui; private String line = ""; public MyWorker(Scanner inputScanner, SimpleGui gui) { this.inputScanner = inputScanner; this.gui = gui; } @Override protected Void doInBackground() throws Exception { while (inputScanner.hasNext()) { // get line from Scanner // use the setter method in case we want to use a PropertyChangeListener later setLine(inputScanner.nextLine()); // send line to the GUI gui.sendLine(getLine()); } return null; } public String getLine() { return line; } // again rigged up to allow use of PropertyChangeListeners public void setLine(String line) { this.line = line; firePropertyChange(LINE, null, line); }}// pre that both the client and server GUI classes shareabstract class DefaultGui implements SimpleGui { // this guy ***must**** be volitile! private volatile boolean myTurn; protected Scanner inputScanner; protected PrintStream out; protected JButton button = new JButton("Blank"); protected Socket socket; protected String name; protected int port; public DefaultGui(int port, String name, boolean myTurn) { this.port = port; this.name = name; this.myTurn = myTurn; } @Override public void sendLine(String nextLine) { button.setText(nextLine); myTurn = true; } public void createGui() { button.addActionListener(e -> actionPerformed(e)); JPanel panel = new JPanel(); panel.setPreferredSize(new Dimension(300, 300)); panel.add(button); Jframe frame = new Jframe(getName()); frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); frame.add(panel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } protected void actionPerformed(ActionEvent e) { if (!myTurn) { return; } out.println(getName()); button.setText(getName()); myTurn = false; } public String getName() { return name; }}class SimpleServer extends DefaultGui { private ServerSocket serverSocket; public SimpleServer(int port, String name, boolean myTurn) throws IOException { super(port, name, myTurn); serverSocket = new ServerSocket(port); new Thread(() -> { try { // accept() blocks the current thread, so must be called on a background thread socket = serverSocket.accept(); inputScanner = new Scanner(socket.getInputStream()); out = new PrintStream(socket.getOutputStream(), true); new MyWorker(inputScanner, this).execute(); } catch (IOException e) { e.printStackTrace(); } }).start(); } }class SimpleClient extends DefaultGui { public SimpleClient(int port, String name, boolean myTurn) throws IOException { super(port, name, myTurn); socket = new Socket("localhost", port); inputScanner = new Scanner(socket.getInputStream()); out = new PrintStream(socket.getOutputStream()); new MyWorker(inputScanner, this).execute(); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)