java选择器_Java NIO (四) 选择器(Selector)

选择器(Selector) 是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector可使一个单独的线程管理多个 Channel,selector 是非阻塞 IO 的核心。

SelectableChannle 的继承树如下图:

c5618b303a590642c4c0858f779e198c.png

选择器(Selector)的应用:

当通道使用register(Selector sel, int ops)方法将通道注册选择器时,选择器对通道事件进行监听,通过第二个参数指定监听的事件类型。

其中可监听的事件类型包括以下:

读 : SelectionKey.OP_READ (1)

写 : SelectionKey.OP_WRITE (4)

连接 : SelectionKey.OP_CONNECT (8)

接收 : SelectionKey.OP_ACCEPT (16)

如果需要监听多个事件是:

int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE ; //表示同时监听读写操作

如何应用请看代码:

public classNIOBlocking2 {

//客户端

@Testpublic void client() throwsException {//1. 获取socketChannel

SocketChannel sChannel =SocketChannel.open();//2. 创建连接

sChannel.connect(new InetSocketAddress("127.0.0.1", 9898));

ByteBuffer buf= ByteBuffer.allocate(1024);//3. 设置通道为非阻塞

sChannel.configureBlocking(false);

@SuppressWarnings("resource")

Scanner scanner= newScanner(System.in);while(scanner.hasNext()) {

String msg=scanner.nextLine();

buf.put((new Date() + ":" +msg).getBytes());

buf.flip();//4. 向通道写数据

sChannel.write(buf);

buf.clear();

}

}

//服务端

@Testpublic void server() throwsException {//1. 获取服务端通道

ServerSocketChannel ssChannel =ServerSocketChannel.open();

ssChannel.bind(new InetSocketAddress(9898));//2. 设置为非阻塞模式

ssChannel.configureBlocking(false);//3. 打开一个监听器

Selector selector =Selector.open();//4. 向监听器注册接收事件

ssChannel.register(selector, SelectionKey.OP_ACCEPT);while (selector.select() > 0) {//5. 获取监听器上所有的监听事件值

Iterator it =selector.selectedKeys().iterator();//6. 如果有值

while(it.hasNext()) {//7. 取到SelectionKey

SelectionKey key =it.next();//8. 根据key值判断对应的事件

if(key.isAcceptable()) {//9. 接入处理

SocketChannel socketChannel =ssChannel.accept();

socketChannel.configureBlocking(false);

socketChannel.register(selector, SelectionKey.OP_READ);

}else if(key.isReadable()) {//10. 可读事件处理

SocketChannel channel =(SocketChannel) key.channel();

readMsg(channel);

}//11. 移除当前key

it.remove();

}

}

}private void readMsg(SocketChannel channel) throwsIOException {

ByteBuffer buf= ByteBuffer.allocate(1024);int len = 0;while ((len = channel.read(buf)) > 0) {

buf.flip();byte[] bytes = new byte[1024];

buf.get(bytes,0, len);

System.out.println(new String(bytes, 0, len));

}

}

}

NIO的非阻塞性:

nio的非阻塞是对于网络通道来说的,需要使用Channel.configureBlocking(false)来设置通道为非阻塞的,如果没设置,默认是阻塞的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值