java nio bio aio

本文详细介绍了Java中的同步阻塞I/O (BIO)、同步非阻塞I/O (NIO) 和异步非阻塞I/O (AIO) 的概念与区别。重点对比了BIO与NIO的不同之处,并解释了AIO如何实现更高效的异步处理。通过具体的Java代码示例展示了如何使用NIO中的通道(Channel)和选择器(Selector)进行高效的数据通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/liuxiao723846/article/details/45066095


java中的IO主要源自于网络和本地文件

 

     IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO

     在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服 务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒 绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。

 

     BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。


         NIO的最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程 中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。


        在NIO的处理方式中,当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。

AIO:  

    HTTP/1.1出现后,有了Http长连接,这样除了超时和指明特定关闭的http header外,这个链接是一直打开的状态的,这样在NIO处理中可以进一步的进化,在后端资源中可以实现资源池或者队列,当请求来的话,开启的线程把请 求和请求数据传送给后端资源池或者队列里面就返回,并且在全局的地方保持住这个现场(哪个连接的哪个请求等),这样前面的线程还是可以去接受其他的请求, 而后端的应用的处理只需要执行队列里面的就可以了,这样请求处理和后端应用是异步的.当后端处理完,到全局地方得到现场,产生响应,这个就实现了异步处 理。

 

     BIO是一个连接一个线程。

   NIO是一个请求一个线程。

   AIO是一个有效请求一个线程。



        大家都知道自从jdk5开始,java中多了java.nio和java.util.concurent包,这两个包可谓威力无穷啊,像tomcat最新版本(用了concurrent包),mina等纷纷在此基础上进行了更新(mina更是直接就通过java.nio来实现的)。其实nio说起来很简单。java通信的基础是socket.和serversocket 在此基础上封装一下,就是socketchannel和serversocketchannel,封装成channel的最大好处就是可以实现non-blocking的通信。然后再加入了一个多路轮询机制,通过观察者模式使得通过单线程就可以同时管理多个channel. 明白了这些之后,放出我的例子来。分别使用socket,channel,selector

实现了java的通信。

 

Server:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.io.IOException;    
  2. import java.net.InetSocketAddress;    
  3. import java.net.ServerSocket;    
  4. import java.net.Socket;    
  5. import java.nio.ByteBuffer;    
  6. import java.nio.channels.*;    
  7. import java.util.Set;    
  8.     
  9.     
  10. public class TestChannel {    
  11.     public static void main(String args[]) throws IOException{    
  12.         TestChannel tt=new TestChannel();    
  13.         //tt.initServerChannel(992);    
  14.         tt.initSelector(992);    
  15.     }    
  16.         
  17.     //最初的java  socket实现方式,直接通过serversocket和socket通信    
  18.     public void initServerSocket(int port) throws IOException{    
  19.         ServerSocketChannel ssc=ServerSocketChannel.open();    
  20.         //ssc.configureBlocking(false);    
  21.         ServerSocket ss=new ServerSocket(port);    
  22.         while(true){    
  23.             Socket socket=ss.accept();    
  24.                 System.out.println("socket accepted");    
  25.                 byte[] buf=new byte[1024];    
  26.                 try{    
  27.                 socket.getInputStream().read(buf);    
  28.                 }    
  29.                 catch(Exception ex){    
  30.                     socket.close();    
  31.                 }    
  32.                 System.out.println(new String(buf));    
  33.                 
  34.         }    
  35.     }    
  36.     //通过Channel实现的non-blocking通信方式    
  37.     public void initServerChannel(int port) throws IOException{    
  38.         ServerSocketChannel ssc=ServerSocketChannel.open();    
  39.         ssc.configureBlocking(false);    
  40.         ServerSocket ss=ssc.socket();    
  41.         ss.bind(new InetSocketAddress(port));    
  42.         while(true){    
  43.             SocketChannel sc=ssc.accept();    
  44.             if(sc!=null){    
  45.                 Socket socket=sc.socket();    
  46.                 System.out.println("socket accepted");    
  47.                 byte[] buf=new byte[1024];    
  48.                 try{    
  49.                 socket.getInputStream().read(buf);    
  50.                 }    
  51.                 catch(Exception ex){    
  52.                     socket.close();    
  53.                 }    
  54.                 System.out.println(new String(buf));    
  55.             }    
  56.         }    
  57.     }    
  58.     //通过selector和channel进行multiplexed通信,像mina就是通过这种方式实现的    
  59.     public void initSelector(int port) throws IOException{    
  60.         Selector selector=Selector.open();    
  61.         //register server channel    
  62.         ServerSocketChannel ssc=ServerSocketChannel.open();    
  63.         ssc.configureBlocking(false);    
  64.         ServerSocket ss=ssc.socket();    
  65.         ss.bind(new InetSocketAddress(port));    
  66.         ssc.register(selector, SelectionKey.OP_ACCEPT);    
  67.         while(true){    
  68.             int interestNo=selector.select();    
  69.             if(interestNo==0)    
  70.                 continue;    
  71.             Set<SelectionKey> keys=selector.selectedKeys();    
  72.             for(SelectionKey key:keys){    
  73.                 //接受Socket连接请求    
  74.                 if(key.isAcceptable()){    
  75.                     SocketChannel sc=ssc.accept();    
  76.                     try{    
  77.                     sc.configureBlocking(false);    
  78.                     sc.register(selector, SelectionKey.OP_READ);    
  79.                     }    
  80.                     catch(Exception ex){    
  81.                         sc.close();    
  82.                     }    
  83.                     System.out.println("connection accepted");    
  84.                     keys.remove(key);    
  85.                 }    
  86.                 else if(key.isReadable()){    
  87.                     SocketChannel sc=(SocketChannel)key.channel();    
  88.                     ByteBuffer bbuf=ByteBuffer.allocate(1024);    
  89.                     try{    
  90.                     sc.read(bbuf);    
  91.                     }    
  92.                     catch(Exception ex){    
  93.                         sc.close();    
  94.                     }    
  95.                     System.out.println(new String(bbuf.array()));    
  96.                     keys.remove(key);    
  97.                 }    
  98.                 else    
  99.                     keys.remove(key);    
  100.                     continue;    
  101.                         
  102.                 }    
  103.             }    
  104.         }    
  105.     }  
 client:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class TestChannelClient {    
  2. public static void main(String args[]) throws UnknownHostException, IOException{    
  3.     Socket sc=new Socket("127.0.0.1",992);    
  4.     OutputStream out=sc.getOutputStream();    
  5.     out.write("hello".getBytes());    
  6.     out.flush();    
  7. }    
  8. }    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值