我正在使用NIO中的Java选择器。我正在使用特定频道和选择器注册我的选择键/兴趣键。现在,我的要求是为特定选择器设置两个或更多兴趣集。
我所做的是制作两个具有不同选择选项的选择键,如下所示:
try {
Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
//FileChannel channel = new FileInputStream("").getChannel();
channel.configureBlocking(false);
SelectionKey key1 = channel.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel.register(selector, SelectionKey.OP_WRITE);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
我的问题是,无论如何我可以避免制作两个不同的键吗?
您可以将二进制或键一起创建单个兴趣:
SelectionKey key = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
一个老问题,虽然需要注意。
请注意,在同一通道上调用register
两次不会添加额外的注册,但会替换之前的注册。
OP提供的代码有几个值得关注的问题:
try {
Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
//====================================================================
// NOTE:
// this is not good - see notes below...
//====================================================================
SelectionKey key1 = channel.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel.register(selector, SelectionKey.OP_WRITE);
//====================================================================
// NOTE 1:
// the 2nd call to channel.register causes the channel to be registered
// only for OP_WRITE, replacing the registration for OP_READ.
// So both lines together makes the first one redundant 'dead code'.
// NOTE 2:
// the key returned in both calls would be the same as the key is
// associated with the channel, regardless of the events we register for
// (changing the registration doesn't change the SelectionKey, it only
// sets another registration for this key).
// NOTE 3:
// ServerSocketChannel should not be registered for OP_READ, OP_WRITE...
// ServerSocketChannel should be registered for OP_ACCEPT
// You may register SocketChannel to OP_READ and OP_WRITE
//====================================================================
} catch (IOException e) { // ...
因此,正如已经指出的那样,正确的方法是使用按位 - 或者,使用以下附加修复:
SocketChannel clientChannel = serverSockChannel.accept();
clientChannel.configureBlocking(false);
SelectionKey key =
clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
这不仅仅是注册两个事件的更好方式 - 否则不起作用。