java - 在 Windows 上线程直到 Thread.join() 才停止

标签 java windows multithreading sockets

方法 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,PlainSocketImpldefines 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/

相关文章:

windows - 为Windows实现个人防火墙,如何判断数据包属于哪个应用程序?

javascript - Node.js 和 MongoDB - 多个异步数据库操作的原子性?

c# - WaitHandle.WaitAny 以匹配 WaitForMultipleObjects 功能

java - 我应该用什么替换 sun.awt.shell.ShellFolder 这样我就不会收到编译警告?

java - Firebase Recyclerview 检索

java - Play框架JSON列表绑定(bind)

node.js - 尝试读取 fullchain.pem 时出现 EPERM 错误

java - javafx中的对话

Windows 上的 Python 2.7,所有多处理示例的 "assert main_name not in sys.modules, main_name"

python - 从另一个线程更新QLabel的内容时,GIF不会进行动画处理