Java之NIO(二)selector socketChannel

上篇文章对NIO进行了简介,对Channel和Buffer接口的使用进行了说明,并举了一个简单的例子来说明其使用方法。

本篇则重点说明selector,Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。

与selector联系紧密的是ServerSocketChannel和SocketChannel,他们的使用与上篇文章描述的FileChannel的使用方法类似,然后与ServerSocket和Socket也有一些联系。

本篇首先简单的进selector进行说明,然后一个简单的示例程序,来演示即时通讯。

Selector

使用传统IO进行网络编程,如下图所示:


每一个到服务端的连接,都需要一个单独的线程(或者线程池)来处理其对应的socket,当连接数多的时候,对服务端的压力极大。并使用socket的getInputStream。Read方法来不断的轮训每个socket,效率可想而知。

而selector则可以在同一个线程中监听多个channel的状态,当某个channel有selector感兴趣的事情发现,selector则被激活。即不会主动去轮询。如下图所示:

 

Selector使用如下示意:

public static void main(String[] args) throws IOException {
      Selector selector = Selector.open();//声明selector
     
      ServerSocketChannel sc = ServerSocketChannel.open();
      sc.configureBlocking(false);//必须设置为异步
      sc.socket().bind(new InetSocketAddress(8081));//绑定端口
     
      //把channel 注册到 selector上
      sc.register(selector, SelectionKey.OP_ACCEPT|SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);
     
      while(true){
         selector.select();//阻塞,直到注册的channel上某个感兴趣的事情发生
         Set<SelectionKey> selectedKeys = selector.selectedKeys();
         Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
         while(keyIterator.hasNext()) {
             SelectionKey key = keyIterator.next();
             if(key.isAcceptable()) {
                 // a connection was accepted by a ServerSocketChannel.
             } else if (key.isConnectable()) {
                 // a connection was established with a remote server.
             } else if (key.isReadable()) {
                 // a channel is ready for reading
             } else if (key.isWritable()) {
                 // a channel is ready for writing
             }
             keyIterator.remove();
         }
      }
     
   }

 

极简即时通讯

本例子是是一个极为简单的例子,很多地方都不完善,但是例子可以很好的说明selector的使用方法。

本例子包含服务端和客户端两个部分,其中服务端采用两个selector,用来建立连接和数据的读写。两个selector在两个线程中。

服务端

/**
 * 简单的即时通讯服务端,采用建立连接 selector和数据 selector分离。很不完善
 *
 */
public class ServerSocketChannelTest {
 
   private static final int SERVER_PORT = 8081;
 
   private ServerSocketChannel server;
 
   private volatile Boolean isStop =
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值