SelectionKey类的使用

SelectionKey类的使用

SelectionKey类标识SelectableChannel在选择器中的注册标记。
在这里插入图片描述

在每次向选择器注册通道时,就会创建一个 选择键(SelectionKey)。通过调用某个键的cancel()方法、关闭其通道,或者通过关闭其选择器取消该键之前,通道一直保持有效。取消某个键不会立即从其选择器中移除它,而是将该键添加到选择器的已取消键集,以便在下一次进行select()方法操作时移除它。可通过调用某个键的isValid()方法来测试其有效性。

选择键包含两个集,是表示为整数值的操作集,其中每一位都表示该键通道所支持的一类可选择操作:

  1. interest集:确定了下一次调用某个选择器的select()方法时,将测试哪类操作的准备就绪信息。创建该键时使用给定的值初始化interest集合,之后可通过interestOps(int)方法对其进行更改。
  2. ready集:标识了这样一类操作,即某个键的选择器检测到该键的通道已为此类操作准备就绪。在创建该键时,ready 集初始化为零,可以在之后的select()方法操作中通过选择器对其进行更新,但不能直接更新它。

选择键的ready集指示,其通道对某个操作类别已准备就绪,该指示只是一个提示,并不保证线程可执行此类别中的操作而不发生线程阻塞。ready集很可能一完成选择操作就是准确的。ready集可能由于外部事件和在相应通道上调用的I/O操作而变得不准确。

SelectionKey类定义了所有已知的操作集位( operation-set bit),但是给定的通道具体支持哪些位则取决于该通道的类型。SelectableChannel 的每个子类都定义了validOps() 方法,该方法返回的集合恰好标识该通道支持的操作。试图设置或测试某个键的通道所不支持的操作集位将导致抛出相应的运行时异常。

通常必须将某个特定于应用程序的数据与某个选择键相关联,如表示高级协议状态的对象和为了实现该协议而处理准备就绪通知的对象。因此,选择键支持将单个任意对象附加到某个键的操作。可通过attach()方法附加对象,然后通过attachment()方法获取该对象。

多个并发线程可安全地使用选择键。一般情况下,读取和写人interest集的操作将与选择器的某些操作保持同步。具体如何执行该同步操作与实现有关:

  • 在一般实现中,如果正在进行某个选择操作,那么读取或写入interest集可能会无限期地阻塞;
  • 在高性能的实现中,可能只会暂时阻塞。无论在哪种情况下,选择操作将始终使用该操作开始时的interest集值

选择器是线程安全的,而键集却不是!

判断是否允许连接SelectableChannel对象

public final boolean isAcceptable()方法的作用是测试此键的通道是否已准备好接受新的套接字连接。调用此方法的形式为k.isAcceptable(),该调用与以下调用的作用完全相同: k.readyOps() & OP_ ACCEPT !=0。如果此键的通道不支持套接字连接操作,则此方法始终返回false。返回值当且仅当readyOps() & OP_ ACCEPT为非零值时才返回true。

public final boolean isConnectable()方法的作用是测试此键的通道是否已完成其套接字连接操作。调用此方法的形式为k.isConnectable(),该调用与以下调用的作用完全相同: k.readyOps() & OP_ CONNECT != 0。如果此键的通道不支持套接字连接操作,则此方法始终返回false。返回值当且仅当readyOps()&OP_CONNECT为非零值时才返回true。

public abstract SelectableChannel channel()方法的作用是返回为之创建此键的通道。即使已取消该键,此方法仍继续返回通道。

判断是否已准备好进行读取

public final boolean isReadable()方法的作用是测试此键的通道是否已准备好进行读取。调用此方法的形式为k.isReadable(),该调用与以下调用的作用完全相同:k.readyOps()&OP_READ!=0。如果此键的通道不支持读取操作,则此方法始终返回false。返回值当且仅当readyOps() & OP_ READ为非零值时才返回true。

服务端:

public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress("localhost", 8088));
            serverSocketChannel.configureBlocking(false);

            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            SocketChannel socketChannel = null;
            boolean isRun = true;
            while (isRun) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        System.out.println("server isAcceptable()");
                        socketChannel = channel.accept();
                        socketChannel.configureBlocking(false);
                        //对socketChannel注册读的事件
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if (key.isReadable()) {
                        System.out.println("server isReadable()");
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int readLength = socketChannel.read(byteBuffer);
                        while (readLength != -1) {
                            System.out.println(new String(byteBuffer.array(), 0, readLength));
                            readLength = socketChannel.read(byteBuffer);
                        }
                        socketChannel.close();
                    }
                    it.remove();
                }
            }
            serverSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

客户端:

public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost", 8088));
            int keyCount = selector.select();
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> it = selectionKeys.iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                if (key.isConnectable()) {
                    //需要在此处使用finishConnect()方法完成连接,因为socketChannel是非阻塞模式
                    while (!socketChannel.finishConnect()) {
                        System.out.println("!socketChannel.finishConnect()-------------");
                    }
                    System.out.println("client isConnectable()");
                    SocketChannel channel = (SocketChannel) key.channel();
                    byte[] writeData = "我来自客户端,你好!服务器!".getBytes();
                    ByteBuffer byteBuffer = ByteBuffer.wrap(writeData);
                    channel.write(byteBuffer);
                    channel.close();
                }
            }
            System.out.println("client end!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//服务端输出
server isAcceptable()
server isReadable()
我来自客户端,你好!服务器!

//客户端输出
client isConnectable()
client end!
判断是否已经准备好进行写入

public final boolean isWritable()方法的作用是测试此键的通道是否已准备好进行写人。调用此方法的形式为k.isWritable(),该调用与以下调用的作用完全相同:k.readyOps()&OP_ WRITE !=0。如果此键的通道不支持写人操作,则此方法始终返回false。 返回值当且readyOps()&OP_WRITE为非零值时才返回true。

服务端与上面的一致。
客户端如下:

public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost", 8088));
            boolean isRun = true;
            while (isRun) {
                int keyCount = selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isConnectable()) {
                        System.out.println("client isConnectable()");
                        if (socketChannel.isConnectionPending()) {
                            while (!socketChannel.finishConnect()) {
                                System.out.println("!socketChannel.finishConnect()--------");
                            }
                            socketChannel.register(selector, SelectionKey.OP_WRITE);
                        }
                    }
                    if (key.isWritable()) {
                        System.out.println("client isWritable()");
                        ByteBuffer byteBuffer = ByteBuffer.wrap("我来自客户端,你好,服务端!".getBytes());
                        socketChannel.write(byteBuffer);
                        socketChannel.close();
                    }
                }
            }
            System.out.println("client end!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//服务端输出
server isAcceptable()
server isReadable()
我来自客户端,你好,服务端!

//客户端输出
client isConnectable()
client isWritable()
返回SelectionKey关联的选择器

public abstract Selector selector()方法的作用是返回SelectionKey关联的选择器。即使已取消该键,此方法仍将继续返回选择器。

在注册操作时传入attachment附件

SelectableChannel类中的public final SelectionKey register(Selector sel, int ops, Objectatt)方法的作用是向给定的选择器注册此通道,返回一个选择键。如果当前已向给定的选择器注册了此通道,则返回表示该注册的选择键。该键的相关操作集将更改为ops,就像调用interestOps(int)方法一样。

  • 如果att参数不为null,则将该键的附件设置为该值。如果已取消该键,则抛出CancelledKeyException异常。
  • 如果尚未向给定的选择器注册此通道,则注册该通道并返回得到的新键。

该键的初始可用操作集是ops,并且其附件是att。可在任意时间调用此方法。如果调用此方法的同时正在进行另一个此方法或configureBlocking()方法的调用,则在另一个操作完成前将首先阻塞该调用。然后,此方法将在选择器的键集上实现同步。因此,如果调用此方法时并发地调用了涉及同一选择器的另一个注册或选择操作,则可能阻塞此方法的调用。如果正在进行此操作时关闭了此通道,则此方法返回的键是已取消的,因此返回键无效。参数sel代表要向其注册此通道的选择器,ops代表所得键的可用操作集,att代表所得键的附件,attr参数可能为null。返回值表示此通道向给定选择器注册的键。

SelectionKey类中的public final Object attachment()方法的作用是获取当前的附加对象。返回值代表当前已附加到此键的对象,如果没有附加对象,则返回null。

public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress("localhost", 8888));
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            SocketChannel socketChannel = null;
            boolean isRun = true;
            while (isRun) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        System.out.println("server isAcceptable()");
                        socketChannel = channel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if (key.isReadable()) {
                        System.out.println("server isReadable()");
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int readLength = socketChannel.read(byteBuffer);
                        while (readLength != -1) {
                            System.out.println(new String(byteBuffer.array(), 0, readLength));
                            readLength = socketChannel.read(byteBuffer);
                        }
                        socketChannel.close();
                    }
                    it.remove();
                }
            }
            serverSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost", 8888));
            boolean isRun = true;
            while (isRun) {
                int keyCount = selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isConnectable()) {
                        System.out.println("client isConnectable()");
                        if (socketChannel.isConnectionPending()) {
                            while (!socketChannel.finishConnect()) {
                                System.out.println("!socketChannel.finishConnect()----");
                            }
                            socketChannel.register(selector, SelectionKey.OP_WRITE, "我使用附件进行注册,我来自客户端,你好服务端");
                        }
                    }
                    if (key.isWritable()) {
                        System.out.println("client isWritable()");
                        ByteBuffer byteBuffer = ByteBuffer.wrap(((String)key.attachment()).getBytes());
                        socketChannel.write(byteBuffer);
                        socketChannel.close();
                    }
                }
            }
            System.out.println("client end!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//服务端输出:
server isAcceptable()
server isReadable()
我使用附件进行注册,我来自客户端,你好服务端
//客户端输出:
client isConnectable()
client isWritable()
设置attachment附件

public final Object attach(Object ob)方法的作用是将给定的对象附加到此键。之后可通过attachment()方法获取已附加的对象。一次只能附加一个对象。调用此方法会导致丟弃所有以前的附加对象。通过附加null可丢弃当前的附加对象。参数ob代表要附加的对象,可以为null。返回值代表先前已附加的对象(如果有),否则返回null。

修改上面的客户端代码:
在这里插入图片描述

//服务端输出
server isAcceptable()
server isReadable()
使用attach(Object)进行注册,我来自客户端,你好服务端!
//客户端输出
client isConnectable()
client isWritable()
获取与设置此键的interest集合

public abstract int interestOps()方法的作用是获取此键的interest集合。可保证返回的集合仅包含对于此键的通道而言有效的操作位。可在任意时间调用此方法。是否受阻塞,以及阻塞时间长短都是与实现相关的。返回值代表此键的interest集合。

public abstract SelectionKey interestOps(int ops)方法的作用是将此键的interest集合设置为给定值。可在任意时间调用此方法。是否受阻塞,以及阻塞时间长短都是与实现相关的。参数ops代表新的interest 集合,返回值代表此选择键。

public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);

            SocketChannel socketChannel1 = SocketChannel.open();
            socketChannel1.configureBlocking(false);

            SocketChannel socketChannel2 = SocketChannel.open();
            socketChannel2.configureBlocking(false);

            Selector selector = Selector.open();
            SelectionKey key1 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            SelectionKey key2 = socketChannel1.register(selector, SelectionKey.OP_CONNECT |
                    SelectionKey.OP_READ);
            SelectionKey key3 = socketChannel2.register(selector, SelectionKey.OP_CONNECT |
                    SelectionKey.OP_READ | SelectionKey.OP_WRITE);

            System.out.println(~key1.interestOps() & SelectionKey.OP_ACCEPT);
            System.out.println(~key1.interestOps() & SelectionKey.OP_CONNECT);
            System.out.println(~key1.interestOps() & SelectionKey.OP_READ);
            System.out.println(~key1.interestOps() & SelectionKey.OP_WRITE);
            System.out.println();
            System.out.println(~key2.interestOps() & SelectionKey.OP_ACCEPT);
            System.out.println(~key2.interestOps() & SelectionKey.OP_CONNECT);
            System.out.println(~key2.interestOps() & SelectionKey.OP_READ);
            System.out.println(~key2.interestOps() & SelectionKey.OP_WRITE);
            System.out.println();
            System.out.println(~key3.interestOps() & SelectionKey.OP_ACCEPT);
            System.out.println(~key3.interestOps() & SelectionKey.OP_CONNECT);
            System.out.println(~key3.interestOps() & SelectionKey.OP_READ);
            System.out.println(~key3.interestOps() & SelectionKey.OP_WRITE);
            System.out.println();
            //使用interestOps(int ops)方法,重新定义感兴趣的事件
            key3.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
            System.out.println(~key3.interestOps() & SelectionKey.OP_ACCEPT);
            System.out.println(~key3.interestOps() & SelectionKey.OP_CONNECT);
            System.out.println(~key3.interestOps() & SelectionKey.OP_READ);
            System.out.println(~key3.interestOps() & SelectionKey.OP_WRITE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
0
8
1
4

16
0
0
4

16
0
0
0

16
0
1
0
判断此键是否有效

public abstract boolean isValid)()方法的作用是告知此键是否有效。键在创建时是有效的,并在被取消、其通道已关闭或者其选择器已关闭之前保持有效。返回值当且仅当此键有效时才返回true。

public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            SelectionKey key1 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println(key1.isValid());
            key1.cancel();
            System.out.println(key1.isValid());
            serverSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述

获取此键的ready操作集合

public abstract int readyOps()方法的作用是获取此键的ready操作集合,可保证返回的集合仅包含对于此键的通道而言有效的操作位,返回值代表此键的ready操作集合。

//服务端
public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress("localhost", 8888));
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            SelectionKey selectionKey1 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            SocketChannel socketChannel = null;
            boolean isRun = true;
            while (isRun) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        System.out.println("server isAcceptable() OP_ACCEPT result=" + (SelectionKey.OP_ACCEPT & ~key.readyOps()));
                        System.out.println("server isAcceptable() OP_CONNECT result=" + (SelectionKey.OP_CONNECT & ~key.readyOps()));
                        System.out.println("server isAcceptable() OP_READ result=" + (SelectionKey.OP_READ & ~key.readyOps()));
                        System.out.println("server isAcceptable() OP_WRITE result=" + (SelectionKey.OP_WRITE & ~key.readyOps()));
                        socketChannel = channel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if (key.isReadable()) {
                        System.out.println("server isReadable() OP_ACCEPT result=" + (SelectionKey.OP_ACCEPT & ~key.readyOps()));
                        System.out.println("server isReadable() OP_CONNECT result=" + (SelectionKey.OP_CONNECT & ~key.readyOps()));
                        System.out.println("server isReadable() OP_READ result=" + (SelectionKey.OP_READ & ~key.readyOps()));
                        System.out.println("server isReadable() OP_WRITE result=" + (SelectionKey.OP_WRITE & ~key.readyOps()));
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int readLength = socketChannel.read(byteBuffer);
                        while (readLength != -1) {
                            System.out.println(new String(byteBuffer.array(), 0, readLength));
                            readLength = socketChannel.read(byteBuffer);
                        }
                        socketChannel.close();
                    }
                    it.remove();
                }
            }
            serverSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//客户端
public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost", 8888));
            boolean isRun = true;
            while (isRun) {
                int keyCount = selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isConnectable()) {
                        System.out.println("server isConnectable() OP_ACCEPT result=" + (SelectionKey.OP_ACCEPT & ~key.readyOps()));
                        System.out.println("server isConnectable() OP_CONNECT result=" + (SelectionKey.OP_CONNECT & ~key.readyOps()));
                        System.out.println("server isConnectable() OP_READ result=" + (SelectionKey.OP_READ & ~key.readyOps()));
                        System.out.println("server isConnectable() OP_WRITE result=" + (SelectionKey.OP_WRITE & ~key.readyOps()));
                        if (socketChannel.isConnectionPending()) {
                            while (!socketChannel.finishConnect()) {
                                System.out.println("!socketChannel.finishConnect()-----");
                            }
                            socketChannel.register(selector, SelectionKey.OP_WRITE);
                            key.attach("我使用附件进行注册,我来自客户端,你好服务端!");
                        }
                    }
                    if (key.isWritable()) {
                        System.out.println("server isWritable() OP_ACCEPT result=" + (SelectionKey.OP_ACCEPT & ~key.readyOps()));
                        System.out.println("server isWritable() OP_CONNECT result=" + (SelectionKey.OP_CONNECT & ~key.readyOps()));
                        System.out.println("server isWritable() OP_READ result=" + (SelectionKey.OP_READ & ~key.readyOps()));
                        System.out.println("server isWritable() OP_WRITE result=" + (SelectionKey.OP_WRITE & ~key.readyOps()));
                        ByteBuffer byteBuffer = ByteBuffer.wrap(((String)key.attachment()).getBytes());
                        socketChannel.write(byteBuffer);
                        socketChannel.close();
                        key.cancel();
                    }
                }
            }
            System.out.println("cllient end!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//服务端输出
server isAcceptable() OP_ACCEPT result=0
server isAcceptable() OP_CONNECT result=8
server isAcceptable() OP_READ result=1
server isAcceptable() OP_WRITE result=4
server isReadable() OP_ACCEPT result=16
server isReadable() OP_CONNECT result=8
server isReadable() OP_READ result=0
server isReadable() OP_WRITE result=4
我使用附件进行注册,我来自客户端,你好服务端!

//客户端输出
server isConnectable() OP_ACCEPT result=16
server isConnectable() OP_CONNECT result=0
server isConnectable() OP_READ result=1
server isConnectable() OP_WRITE result=4
server isWritable() OP_ACCEPT result=16
server isWritable() OP_CONNECT result=8
server isWritable() OP_READ result=1
server isWritable() OP_WRITE result=0
取消操作

public abstract void cancel()方法的作用是请求取消此键的通道到其选择器的注册。一旦返回,该键就是无效的,并且将被添加到其选择器的已取消键集中。在进行下一次选择操作时,将从所有选择器的键集中移除该键。如果已取消了此键,则调用此方法无效。一旦取消某个键,SelectionKey.isValid) 方法返回false。可在任意时间调用cancel()方法。此方法与选择器的已取消键集保持同步,因此,如果通过涉及同一选择器的取消或选择操作并发调用它,则它可能会暂时受阻塞。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SelectionKey 可以表示四种事件型,分别是: 1. 可读事件(OP_READ):表示对应的通道已经准备好读取数据。 2. 可写事件(OP_WRITE):表示对应的通道已经可以写入数据。 3. 连接事件(OP_CONNECT):表示对应的通道已经建立连接。 4. 接收事件(OP_ACCEPT):表示 ServerSocketChannel 接受到了一个新的连接请求。 这四种事件型可以通过 OR 运算符连接起来,例如: int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 这表示我们对读写事件都感兴趣。 ### 回答2: SelectionKey是Java NIO中的一个关键概念,它代表了一个可选择的事件和与该事件关联的通道。SelectionKey可以表示四种不同的事件:可读、可写、连接、接收。 1. 可读事件(OP_READ):当一个通道可读时,此事件会被通知。这通常意味着通道里有数据可以被读取。 2. 可写事件(OP_WRITE):当一个通道可写时,此事件会被通知。这通常意味着现在可以将数据写入到通道中。 3. 连接事件(OP_CONNECT):当一个连接已经在建立中时,此事件会被通知。这通常意味着正在进行的连接操作已经完成。 4. 接收事件(OP_ACCEPT):当一个ServerSocketChannel接受一个新的连接时,此事件会被通知。这通常意味着可以通过accept()方法接收一个新的SocketChannel。 总的而言,SelectionKey可以表示四种不同的事件,分别是可读、可写、连接和接收。在使用Java NIO进行非阻塞IO编程时,SelectionKey非常重要,通过它我们可以知道通道的状态和事件是否发生,从而做出相应的处理。 ### 回答3: SelectionKey是Java NIO库中的一个关键,用于表示特定通道在Selector中的注册状态以及所关注的事件型。SelectionKey总共有四个事件型,分别是: 1. OP_READ(读事件):表示通道已经准备好进行读取操作,当通道内部缓冲区可读时,该事件会被触发。 2. OP_WRITE(写事件):表示通道已经准备好进行写入操作,当通道内部缓冲区可写时,该事件会被触发。 3. OP_CONNECT(连接事件):表示与远程主机建立连接已经就绪,当通道连接成功时,该事件会被触发。 4. OP_ACCEPT(接受事件):表示可以接受新的连接请求,当ServerSocketChannel接受到新的连接时,该事件会被触发。 通过注册SelectionKey时指定事件型,可以在Selector监听到特定事件发生时做出相对应的处理操作。在实际编程中,常常结合使用位运算对多个事件进行组合注册,如:SelectionKey.OP_READ | SelectionKey.OP_WRITE 表示同时关注读和写两个事件。 需要注意的是,一个SelectionKey通常只能关联一个事件型,但一个通道可以注册多个SelectionKey与之关联,即一个通道可以在不同的Selector中注册不同的事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值