1

我创建了 AsynchronousServerSocketChannel 并且一切都很好,直到我想要关闭服务器套接字套接字。我使用特殊消息在客户端上创建 AsynchronousSocketChannel ,该消息调用函数来关闭服务器和所有套接字通道,服务器已关闭但最终块永远不会执行,为什么?

校验码:

 public void openServerSocket(int sport) {


    port = sport;
    policyFile = createPolicy(new String[]{"*:"+port});
    try {

        //group = AsynchronousChannelGroup.withThreadPool(Executors.newSingleThreadExecutor());
        //group.awaitTermination(1, TimeUnit.SECONDS);
        server = AsynchronousServerSocketChannel.open();
        server.bind(new InetSocketAddress(sport));


        server.accept(null, this);

       while(isOpen) {

            //System.out.println("running server socket");

        }
    }catch(Exception ex) {
        this.message = ex.getMessage();
        System.out.println("Server: " + ex.getMessage());
    }finally {

        System.out.println("Finall serversocket closing!");
        for(SocketHandler sh : sockets) {
            sh.close();
        }

        if(server != null) {
            try {
                server.close();
                server = null;
            }catch(Exception ex2) {
                this.message = ex2.getMessage();
            }
        }


        sockets.clear();
        sockets = null;
        //this.message = "server socket closed";

        System.out.println("server socket down");
    }

}

@Override
public void completed(AsynchronousSocketChannel socket, Void attachment) {

    System.out.println("new connection");
    SocketHandler sh = new SocketHandler(socket, this);

    server.accept(null, this);
}

@Override
public void failed(Throwable exc, Void attachment) {

    System.out.println("Server Failed accept:" + exc.getMessage());
}


public void closeServerSocket() {

    System.out.println("Closing server socket! " + server);
    this.isOpen = false;

}

所以函数 closeServerSocket 被调用,我将 false 设置为变量 isOpen ,它一直在循环,但是当我将 false 设置为 isOpen var 时,while 仍在循环并且最终永远不会执行?

4

1 回答 1

1

这看起来像是几个线程之间的通信问题。从代码中我猜你的循环运行在与你的类方法while(isOpen)不同的线程中。closeServerSocket()要验证这一点,请添加Thread.currentThread()到您的打印语句中。

如果是这种情况,您可以通过声明isOpen为来纠正这种情况volatile。如果没有,volatile则无法保证任何其他线程是否以及何时会看到写入的值。有了volatile它可以保证(我对happens-before的解释)稍后访问变量的线程(根据挂钟时间)将看到更改的值。

而不是volatile您可能更喜欢AtomicBoolean.

于 2014-04-25T19:56:25.103 回答