服务器关闭时关闭选择器

Closing the Selector when server is shutting down

当我想关闭服务器时,我需要关闭阻塞线程的选择器。所以,我从主线程调用 selector.close(),这有助于解锁 selector.select(); 但是 selector 并没有像我猜的那样抛出 ClosedSelectorException 异常:

while (true) {

    try {

        // Blocks until a 'socket' is ready registered with selector is ready.
        selector.select();
    } 
    catch (ClosedSelectorException ex) {

        // Never reached?
        ex.printStackTrace();
    }
    catch (IOException ex) {

        // Never reached?  
        ex.printStackTrace();

    }

    // ...

而是在后面的几行抛出异常:

Set<SelectionKey> readyKeys = selector.selectedKeys();

所以我想做两件事:

我应该使用布尔标志、中断线程还是退出循环?

So I want to do two things:

Detect if the selector was closed when select() unblocks. (possible?)

After that I want to break from the while(true) and let the thread stop.

如果您查看 Selectorclose 方法的文档,您会看到它说 close 方法调用 wakeup使当前 Selector(如果等待)立即变为 return。 如果您查看 Selector 的文档,您会发现它有一个名为 isOpen.

的方法

public abstract boolean isOpen()

Tells whether or not this selector is open.

您需要做的就是在调用 selector.select() 后立即检查 selector.isOpen() return 是否为假,如果 break 退出 while 循环 return是假的。您还应该将使用 selector 的任何代码移动到 try-catch 块中。不需要单独的 boolean 标志来实现这一点。这是您修改后的代码的外观:

    try {

       // Blocks until a 'socket' is ready registered with selector is ready.
        selector.select();
        if(!selector.isOpen()) {
            break;//graceful exit since selector was not in use anyway
        }
        Set<SelectionKey> readyKeys = selector.selectedKeys();
        // ...        
    
     } catch (ClosedSelectorException ex) {

        // selector was closed while being used
        ex.printStackTrace();
     } catch (IOException ex) {

        // some other exception
        ex.printStackTrace();
       
    }
             

使用 isOpen 的优点是您现在可以确定您的服务器是正常关闭(未打印错误)还是在 activity 期间关闭19=](错误打印)

这里假设 whie(true) 循环是在 Thread 的 运行 方法中定义的。