服务器关闭时关闭选择器 [英] Closing the Selector when server is shutting down
问题描述
当我想关闭服务器时,我需要关闭阻塞线程的选择器.因此,我从主线程调用了selector.close()
,这有助于取消阻止selector.select();
,但是选择器不会抛出ClosedSelectorException
异常,就像我猜想的那样:
When I want to close the server, I will need to close Selector which is blocking the Thread. So, I call selector.close()
from the main thread which helps to unblock selector.select();
But the selector doesn't throw ClosedSelectorException
exception as it was supposed to I guess:
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();
}
// ...
但是它会在以后的行中引发异常:
But rather it throws the exception at the later lines:
Set<SelectionKey> readyKeys = selector.selectedKeys();
所以我想做两件事:
- 检测在select()解除阻止时关闭选择器的情况. (可能吗?)
- 之后,我想从
while(true)
中断并让线程停止.
- 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.
我应该使用布尔标志,中断线程还是中断循环?
And should I use a boolean flag, interrupt the thread, or break from loop?
推荐答案
所以我想做两件事:
So I want to do two things:
检测在select()解除阻止时关闭选择器的情况. (可能吗?)
Detect if the selector was closed when select() unblocks. (possible?)
之后,我想从while(true)中断并让线程 停止.
After that I want to break from the while(true) and let the thread stop.
如果您查看Selector中的rel ="nofollow noreferrer">关闭方法,您会看到它说close
方法调用wakeup
,这将使当前的Selector
(如果正在等待)立即返回.
如果查看Selector
的文档,您会发现它具有一种称为
If you take a look at the docs for the close method in Selector
, you will see that it says that the close
method calls wakeup
which will make the current Selector
(if waiting) to return immediately.
If you take a look at the docs for Selector
,, you will see that it has a method called isOpen.
公共抽象布尔isOpen()
public abstract boolean isOpen()
告诉此选择器是否打开.
Tells whether or not this selector is open.
您需要做的只是检查selector.isOpen()
在调用selector.select()
之后是否立即返回false,如果break
返回false,则只需在break
循环之外进行检查.您还应该在try-catch
块内移动所有使用selector
的代码.不需要单独的boolean
标志来实现此目的.这就是修改后的代码的外观:
All you need to do is to check if selector.isOpen()
returns false immediately after you call selector.select()
and simply break
out of your while loop if it returns false. You should also move any code that uses the selector
inside the try-catch
block. There is no need to have a separate boolean
flag to achieve this. This is how your modified code should look :
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
的优势在于,您现在将能够确定服务器是正常关闭(无错误打印)还是在selector
上的某些活动之间关闭(有错误打印)
The advantage of using isOpen
is that you will now be able to identify whether your server was shutdown gracefully (no error printed) or it was shutdown in between some activity on the selector
(error printed)
这里的假设是whie(true)
循环是在Thread
的run方法中定义的.
The assumption here is that the whie(true)
loop is defined inside the run method of your Thread
.
这篇关于服务器关闭时关闭选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!