Java 服务器关闭时关闭选择器

Java 服务器关闭时关闭选择器,java,multithreading,sockets,selector,nio,Java,Multithreading,Sockets,Selector,Nio,当我想关闭服务器时,我需要关闭阻塞线程的选择器。因此,我从主线程调用selector.close(),这有助于解除阻止selector.select()但是选择器不会像我猜想的那样抛出ClosedSelectorException异常: while (true) { try { // Blocks until a 'socket' is ready registered with selector is ready. selector.select()

当我想关闭服务器时,我需要关闭阻塞线程的选择器。因此,我从主线程调用
selector.close()
,这有助于解除阻止
selector.select()但是选择器不会像我猜想的那样抛出
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 readyKeys=selector.selectedKeys()

所以我想做两件事:

  • 在select()解除阻止时检测选择器是否已关闭。(可能吗?)
  • 之后,我想从
    中断while(true)
    ,让线程停止
我应该使用布尔标志、中断线程还是中断循环

所以我想做两件事:

在select()解除阻止时检测选择器是否已关闭。(可能吗?)

在那之后,我想从while(true)中断,让线程 停下来

如果您查看
选择器
中方法的文档,就会发现
关闭
方法调用
唤醒
,这将使当前的
选择器
(如果等待)立即返回。 如果您查看
选择器的文档,您将看到它有一个名为的方法

公共抽象布尔等参元()

指示此选择器是否打开

您只需在调用
selector.select()
后立即检查
selector.isOpen()
是否返回false,如果返回false,只需将
中断
退出while循环即可。您还应该在
try catch
块内移动使用
选择器的任何代码。不需要使用单独的
布尔
标志来实现这一点。以下是修改后的代码的外观:

    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();
       
    }
             
试试看{
//阻止,直到“套接字”准备就绪并注册到选择器准备就绪。
selector.select();
如果(!selector.isOpen()){
break;//退出,因为选择器未被使用
}
设置readyKeys=selector.selectedKeys();
// ...        
}捕获(关闭选择例外){
//选择器在使用时已关闭
例如printStackTrace();
}捕获(IOEX异常){
//还有一些例外
例如printStackTrace();
}
使用
isOpen
的优点是,您现在可以确定服务器是正常关闭(未打印错误),还是在
选择器上的某些活动之间关闭(打印错误)


这里的假设是
whie(true)
循环是在
线程的run方法中定义的

您是否尝试过从异常处理程序返回?循环将继续到下一个方法,该方法将抛出一个未处理的ClosedSelectorException,因为选择器已经关闭。只需将
..
放入
try
块中。@EJP不会导致程序打印出异常日志吗?不,它将导致
捕获中出现“从未到达”(已关闭的选民)
块,您可以在其中做任何您想做的事情。@EJP我想说的是,如果在我们继续做任何工作之前关闭了
选择器,那么什么都不应该发生,线程应该结束。如果在我们继续做一些工作之后关闭
选择器,这是一个例外情况。前者实际上不是例外我们不应该使用副作用(使用关闭的选择器执行操作时发生异常)作为退出线程的手段。这样更好。一方面,您可以通知“选择器正常关闭”和“选择器异常关闭”但是我不确定是否会出现
closedselectrorexception
。你在哪里和什么时候关闭
selector
?。你能保证其他使用你的代码的开发人员不会在
selector
做一些工作时意外地关闭它吗?好的,我现在明白了。选择器可以在执行
isOpen
后关闭。此时异常将非常有用。我从主线程关闭它以停止服务器线程。准确地说。很高兴您终于理解了我所说的:)