java NIO、BIO、AIO区别

小鱼儿 2021-05-12 11:51 637阅读 0赞

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

  1. IO的方式通常分为几种,**同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO**
  2. JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服 务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒 绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。
  3. BIONIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。

Center

  1. NIO的最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程 中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。
  2. NIO的处理方式中,当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。

AIO:  

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

  NIO是一个请求一个线程。

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

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

实现了java的通信。

Server:

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

client:

  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. }

发表评论

表情:
评论列表 (有 0 条评论,637人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java】equals和==区别

    1.==介绍 ==:它是一个运算符,如果操作两边都是对象,比较的是它们在内存中的存放地址,如果两个指向同一个对象,则为true,否则为false,如果两边是基本数据类型,则比

    相关 JAVA堆栈的区别

        1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。       

    相关 java &和&&的区别

    两个都是表示与的运算,&表示逻辑与和按位与,&&表示短路与。 当要判断两个及两个条件以上时,如果用&它会把两个条件都去执行,就可能会报错;如果用&&就先去判断第一个条件,如果