方法 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
超时。这是有意的,因此只有一秒钟的超时。这一切都可以在其他平台上正常运行。我正在中断所有线程然后加入它们以确保它们真正停止。我最担心的是为什么这些线程没有像它们应该的那样同时超时。
最佳答案
对于 *nix 操作系统,套接字实现不会在任何地方锁定 accept
。
对于 Windows,PlainSocketImpl
类 defines accept
as synchronized
:
protected synchronized void accept(SocketImpl s) throws IOException {
// ...
}
accept
一次只被一个线程执行。 1 秒超时仅在最终获取锁后由 native accept
考虑。
我不知道这是不是故意的,你必须在 Java 邮件列表中询问。
关于java - 在 Windows 上线程直到 Thread.join() 才停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41841020/