该方法stopServer()
服务器在Mac,Linux和UNIX计算机上运行良好,但当我尝试在Windows上关闭时,我发现它至少需要一秒 由于ServerSocket
的超时而导致套接字关闭。我希望它们像在Linux,Mac等中一样关闭,而不是在我调用Thread.join()
时关闭。
服务器代码
public class FileServer {
private ArrayList<Thread> sockets = new ArrayList<>();
private ServerSocket fileServer;
public void startServer(int port, int maxThreads, int timeout) throws IOException {
fileServer = new ServerSocket();
fileServer.setPerformancePreferences(1, 0, 1);
fileServer.bind(new InetSocketAddress(port));
for (int threads = 0; threads < maxThreads; threads++) {
sockets.add(new Thread(new ServerInit(fileServer, timeout)));
System.out.println("Socket " + threads + " initialized...");
}
for (int socket = 0; socket < sockets.size(); socket++) {
(sockets.get(socket)).start();
System.out.println("Socket " + socket + " started!");
}
}
public void stopServer() {
if (fileServer.isBound()) {
for (int thread = 0; thread < sockets.size(); thread++) {
sockets.get(thread).interrupt();
}
for (int thread = 0; thread < sockets.size(); thread++) {
try {
if (sockets.get(thread).isAlive()) {
sockets.get(thread).join();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class ServerInit implements Runnable {
private ServerSocket server;
private int timeout;
public ServerInit(ServerSocket server, int timeout) {
this.server = server;
this.timeout = timeout;
}
public void run() {
while (!Thread.interrupted()) {
try {
server.setSoTimeout(1000);
Socket client = server.accept();
client.setSoTimeout(timeout);
processRequest(receiveRequest(client), client);
client.close();
} catch (SocketTimeoutException ste) {
} catch (IOException io) {
io.printStackTrace();
}
}
System.out.println("Socket closed");
}
}
为什么线程要求我加入它们才会退出while
循环?我已经测试过并且确定每个线程都在启动,并且每个线程都被正确中断。
此外,如果我将System.out.println()
置于while
循环中,则只能打印一个主题。
修改
我更了解它必须等待accept
超时。这是预期的,因此只有一秒超时。所有都可以在其他平台上完美运行。我正在打断所有线程然后加入它们以确保它们实际停止。我最担心的是为什么这些线程不应该同时超时。
答案 0 :(得分:2)
对于* nix操作系统,套接字实现在此过程中的任何位置都不会锁定accept
。
对于Windows,PlainSocketImpl
类defines accept
as synchronized
:
protected synchronized void accept(SocketImpl s) throws IOException {
// ...
}
发生的事情是accept
一次只能由一个线程执行。在最终获得锁定后,1秒超时仅由本机accept
进行计算。
我无法判断这是否是故意的,您必须在Java邮件列表中询问。