线程直到Windows上的Thread.join()才停止

时间:2017-01-24 23:49:22

标签: 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超时。这是预期的,因此只有一秒超时。所有都可以在其他平台上完美运行。我正在打断所有线程然后加入它们以确保它们实际停止。我最担心的是为什么这些线程不应该同时超时。

1 个答案:

答案 0 :(得分:2)

对于* nix操作系统,套接字实现在此过程中的任何位置都不会锁定accept

对于Windows,PlainSocketImpldefines accept as synchronized

protected synchronized void accept(SocketImpl s) throws IOException {
    // ...
}

发生的事情是accept一次只能由一个线程执行。在最终获得锁定后,1秒超时仅由本机accept进行计算。

我无法判断这是否是故意的,您必须在Java邮件列表中询问。