NIO:同步非壅闭IO
来源:BIO是同步壅闭IO利用,当线程在处理任务时,另一方会壅闭着等待该线程的履行结束,为了前进效率,,JDK1.4后,引入NIO来提高数据的通讯功能
NIO中接收Reactor方案形式,注册的汇集点为Selector,NIO有三个紧张构成部门:Channel(通道)、Buffer(缓冲区)、Selector(选择器)
Reactor方案形式:Reactor形式是一种被动事情处理形式,即当某个特定事情发作时触发事情,可参考,https://blog.csdn.net/feimataxue/article/details/7642638,https://www.cnblogs.com/bitkevin/p/5724410.html
NIO接收了轮询的方法来调查事情是否履行结束,如:A让B打印某个文件,BIO会不断等待着B返回,期间自己不做其他事变,而NIO则会不断的问询B是否完成,未完成则处理自己的时,直至B完成
Channel(通道):Channel是一个目标,能够通过它读取和写入数据
Selector(目标选择器):Selector是一个目标,它能够注册到很多个Channel上,监听各个Channel上发作的事情,并且能够或许根据事情状况决议Channel读写
代码实现:(此实现参考网络上可用的例子)
NIO客户端实现:
packagecom.learn.nio.client;
importcom.study.info.HostInfo;
importcom.study.util.InputUtil;
importjava.net.InetSocketAddress;
importjava.nio.ByteBuffer;
importjava.nio.channels.SocketChannel;
publicclassNIOEchoClient{
publicstaticvoidmain(String[]args)throwsException{
SocketChannelclientChannel=SocketChannel.open();
clientChannel.connect(newInetSocketAddress(HostInfo.HOST_NAME,HostInfo.PORT));
ByteBufferbuffer=ByteBuffer.allocate(50);
booleanflag=true;
while(flag){
buffer.clear();
Stringinput=InputUtil.getString("请输入待发送的信息:").trim();
buffer.put(input.getBytes());//将数据存入缓冲区
buffer.flip();//重置缓冲区
clientChannel.write(buffer);//发送数据
buffer.clear();
intread=clientChannel.read(buffer);
buffer.flip();
System.err.print(newString(buffer.array(),0,read));
if("byebye".equalsIgnoreCase(input)){
flag=false;
}
}
clientChannel.close();
}
}
NIO服务端实现:
packagecom.learn.nio.server;
importcom.study.info.HostInfo;
importjava.net.InetSocketAddress;
importjava.nio.ByteBuffer;
importjava.nio.channels.SelectionKey;
importjava.nio.channels.Selector;
importjava.nio.channels.ServerSocketChannel;
importjava.nio.channels.SocketChannel;
importjava.util.Iterator;
importjava.util.Set;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassNIOEchoServer{
privatestaticclassEchoClientHandleimplementsRunnable{
//客户端
privateSocketChannelclientChannel;
//循环竣事标记
privatebooleanflag=true;
publicEchoClientHandle(SocketChannelclientChannel){
this.clientChannel=clientChannel;
}
@Override
publicvoidrun(){
ByteBufferbyteBuffer=ByteBuffer.allocate(50);
try{
while(this.flag){
byteBuffer.clear();
intread=this.clientChannel.read(byteBuffer);
Stringmsg=newString(byteBuffer.array(),0,read).trim();
StringoutMsg="【Echo】"+msg+"\n";//回应信息
if("byebve".equals(msg)){
outMsg="会话竣事,下次再见!";
this.flag=false;
}
byteBuffer.clear();
byteBuffer.put(outMsg.getBytes());//回传信息放入缓冲区
byteBuffer.flip();
this.clientChannel.write(byteBuffer);//回传信息
}
}catch(Exceptione){
e.printStackTrace();
}
}
}
publicstaticvoidmain(String[]args)throwsException{
//为了功能问题及相应时刻,设置固定巨细的线程池
ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
//NIO根据Channel控制,所以有Selector办理悉数的Channel
ServerSocketChannelserverSocketChannel=ServerSocketChannel.open();
//设置为非壅闭形式
serverSocketChannel.configureBlocking(false);
//设置监听端口
serverSocketChannel.bind(newInetSocketAddress(HostInfo.PORT));
//设置Selector办理悉数Channel
Selectorselector=Selector.open();
//注册并设置毗邻时处理
serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
System.out.println("服务发动乐成,监听端口为:"+HostInfo.PORT);
//NIO运用轮询,当有恳求毗邻时,则发动一个线程
intkeySelect=0;
while((keySelect=selector.select())>0){
SetselectionKeys=selector.selectedKeys();
Iteratoriterator=selectionKeys.iterator();
while(iterator.hasNext()){
SelectionKeynext=iterator.next();
if(next.isAcceptable()){//假如是毗邻的
SocketChannelaccept=serverSocketChannel.accept();
if(accept!=null){
executorService.submit(newEchoClientHandle(accept));
}
iterator.remove();
}
}
}
executorService.shutdown();
serverSocketChannel.close();
}
}
工具类:
packagecom.study.util;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
publicclassInputUtil{
privatestaticfinalBufferedReaderKEYBOARD_INPUT=newBufferedReader(newInputStreamReader(System.in));
privateInputUtil(){
}
publicstaticStringgetString(Stringprompt){
booleanflag=true;//数据承受标记
Stringstr=null;
while(flag){
System.out.println(prompt);
try{
str=KEYBOARD_INPUT.readLine();//读取一行数据
if(str==null||"".equals(str)){
System.out.println("数据输入过错,不允许为空!");
}else{
flag=false;
}
}catch(IOExceptione){
e.printStackTrace();
}
}
returnstr;
}
}
packagecom.study.info;
publiccalssHostInfo{
publicstaticfinalStringHOST_NAME="localhost";
publicstaticfinalintPORT=9999;
}