最近我正在做多线程聊天应用程序。现在我在服务器上挣扎。我正试图通过引入新字段online
来停止服务器,但这无济于事。
import view.ChatHub;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatServer extends Thread {
// All client names, so we can check for duplicates upon registration.
private static Set<String> names = new HashSet<>();
// The set of all the print writers for all the clients, used for broadcast.
private static Set<PrintWriter> writers = new HashSet<>();
private ChatHub frame;
private int port;
private boolean online;
private ExecutorService pool;
public ChatServer(int port) throws IOException {
System.out.println("The chat server is running...");
this.frame = new ChatHub(this);
this.port = port;
this.online = true;
this.pool = Executors.newFixedThreadPool(500);
this.start();
}
@Override
public void run() {
while (this.online) {
try (ServerSocket listener = new ServerSocket(this.port)) {
this.pool.execute(new Handler(listener.accept(), this.names, this.writers));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stopChatServer() {
this.pool.shutdown();
this.online = false;
}
public Set<String> getNames() {
return this.names;
}
public Set<PrintWriter> getWriters() {
return this.getWriters();
}
public ChatHub getFrame() {
return this.frame;
}
public int getPort() {
return this.port;
}
}
这里我要关闭服务器:
import Client.ChatClient;
import Server.ChatServer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class ChatHub extends JFrame{
JTextField textField;
JTextArea messageArea;
public ChatHub(ChatServer server) {
new JFrame("Chatter");
this.textField = new JTextField(50);
this.messageArea = new JTextArea(16,50);
this.textField.setEditable(true);
this.messageArea.setEditable(false);
this.getContentPane().add(this.textField, BorderLayout.SOUTH);
this.getContentPane().add(new JScrollPane(this.messageArea), BorderLayout.CENTER);
this.pack();
// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
server.stopChatServer();
}
});
this.setVisible(true);
}
public void appendMessage(String line) {
messageArea.append(line + "\n");
}
public JTextField getTextField() {
return this.textField;
}
public JTextArea getMessageArea() {
return this.messageArea;
}
public void nameAccepted(String line) {
this.setTitle("Chatter - " + line.substring(13));
textField.setEditable(true);
}
}
我还尝试使用方法run
,而只打印一些String
。但是当它离开run
方法时,程序仍在工作。有什么建议么?预先感谢。
我还尝试如下实现run()
:
@Override
public void run() {
while (this.online) {
System.out.println("Some String");
}
System.out.println(this.isAlive() + "\n");
}
它最终会输出true
。
答案 0 :(得分:0)
您是否尝试将online
属性声明为volatile
?
private volatile boolean online = true;
如果您未将属性声明为volatile
,则JIT编译器可以假定您的布尔属性不会被另一个线程更改。因此,它可能会将您的运行方法优化为
public void run() {
if (!online)
return;
while(true) {
try(/*...*/) {
// ...
} catch(/*...*/) {
// ...
}
}
}
答案 1 :(得分:0)
也许您在这里还有另一个问题(与Swing相关):
您的new JFrame("Chatter")
仅创建一个新的JFrame,并且对此不执行任何操作。您必须调用super("Chatter");
才能调用超级构造函数
尝试
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)