一、Selector和SelectionKey中的常用方法
1、Selector选择器,socket通道可以在选择器上注册,并绑定选择键SelectorKey,同时可以添加一个附加的对象进行标志。当触发选择键时,对应的选择器上感兴趣的事件也将被执行。
2、阻塞io是每个客户端发送请求,对应一个服务端,服务端等待。请求完毕后,等待着服务端的响应或者无响应。cpu大部分时间空闲,线程多,开销大。非阻塞io基于事件机制,利用单线程seletor通过是否存在该事件进行阻塞。充分利用资源。
<span style="font-family:KaiTi_GB2312;">public abstract class Selector {
public static Selector open( ) throws IOException;//打开选择器
public abstract boolean isOpen( ); //判断选择器是否打开
public abstract void close( ) throws IOException; //关闭选择器
public abstract SelectionProvider provider( ); //调用此方法可以获取选择器的具体实现的类
public abstract int select( ) throws IOException;//单线程模式,阻塞该线程,使所有客户端请求处于等待状态,直到一个合适的事件就绪
public abstract int select (long timeout) throws IOException;//阻塞事件
public abstract int selectNow( ) throws IOException; //任何时刻均不阻塞,若没有对应的事件则直接返回,并继续执行后续代码
public abstract void wakeup( );
public abstract Set keys( );//返回选择器感兴趣的事件集合
public abstract Set selectedKeys( );//返回选择器感兴趣的事件集合
}</span>
<span style="font-family:KaiTi_GB2312;">package java.nio.channels;
public abstract class SelectionKey {
public static final int OP_READ;//通道读就绪状态
public static final int OP_WRITE;//写就绪状态
public static final int OP_CONNECT;//连接就绪状态
public static final int OP_ACCEPT;//接收就绪状态
public abstract SelectableChannel channel( ); //获取关键件标记的通道
public abstract Selector selector( ); //获取对该选择键感兴趣的选择器
public abstract void cancel( );//取消选择键,将会导致选择器无效
public abstract boolean isValid( );
public abstract int interestOps( ); //返回所有的选择键的位与结果
public abstract void interestOps (int ops); //添加感兴趣的选项
public abstract int readyOps( );
public final boolean isReadable( );//判断是否可读就绪
public final boolean isWritable( );
public final boolean isConnectable( );
public final boolean isAcceptable( );
public final Object attach (Object ob);//标记通道的同时,可以绑定一个对象对通道进行标志
public final Object attachment( );//获取该对象
}</span>
二、服务端演示代码
<span style="font-family:KaiTi_GB2312;">package selector;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;
public class TestServerSelector {
public static void main(String[] args) throws IOException {
ServerSocketChannel server = ServerSocketChannel.open();// 打开服务端通道
ServerSocket socket = server.socket();
server.configureBlocking(false);
socket.bind(new InetSocketAddress(999));// 绑定一个端口
Selector open = Selector.open();
server.register(open,SelectionKey.OP_ACCEPT);//注册接收事件
while (true) {
int select = open.select();//使含有该选择器的通道线程阻塞,直到有一个事件就绪
if(select == 0) continue;
Set<SelectionKey> selectedKeys = open.selectedKeys();//获取所有的关键键
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {//遍历每个键并进行判断
SelectionKey selectionKey = (SelectionKey) iterator.next();
if(selectionKey.isConnectable()) {
}
if(selectionKey.isAcceptable()) {//服务器端只对这种事件感兴趣
System.out.println("连接上服务器");
}
}
}
}
}</span>