1. 传统的 IO 流都是阻塞式的。也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。因此,在完成网络通信进行 IO操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降。
  2. Java NIO 是非阻塞模式的。当线程从某通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。线程通常将非阻塞 IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。因此,NIO 可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端。

选择器(Selector)

  1. 选择器(Selector) 是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector可使一个单独的线程管理多个 Channel。Selector 是非阻塞 IO 的核心。
  2. SelectableChannle 的结构如下图:

阻塞式IO流操作示例:

  1. package com.soyoungboy.nio;
  2.  
  3. import java.io.IOException;
  4. import java.net.InetSocketAddress;
  5. import java.nio.ByteBuffer;
  6. import java.nio.channels.FileChannel;
  7. import java.nio.channels.ServerSocketChannel;
  8. import java.nio.channels.SocketChannel;
  9. import java.nio.file.Paths;
  10. import java.nio.file.StandardOpenOption;
  11.  
  12. import org.junit.Test;
  13.  
  14. public class TestBlockingNIO2 {
  15.  
  16. //客户端
  17. @Test
  18. public void client() throws IOException{
  19. SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  20.  
  21. FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
  22.  
  23. ByteBuffer buf = ByteBuffer.allocate(1024);
  24.  
  25. while(inChannel.read(buf) != -1){
  26. buf.flip();
  27. sChannel.write(buf);
  28. buf.clear();
  29. }
  30.  
  31. sChannel.shutdownOutput();
  32.  
  33. //接收服务端的反馈
  34. int len = 0;
  35. while((len = sChannel.read(buf)) != -1){
  36. buf.flip();
  37. System.out.println(new String(buf.array(), 0, len));
  38. buf.clear();
  39. }
  40.  
  41. inChannel.close();
  42. sChannel.close();
  43. }
  44.  
  45. //服务端
  46. @Test
  47. public void server() throws IOException{
  48. ServerSocketChannel ssChannel = ServerSocketChannel.open();
  49.  
  50. FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
  51.  
  52. ssChannel.bind(new InetSocketAddress(9898));
  53.  
  54. SocketChannel sChannel = ssChannel.accept();
  55.  
  56. ByteBuffer buf = ByteBuffer.allocate(1024);
  57.  
  58. while(sChannel.read(buf) != -1){
  59. buf.flip();
  60. outChannel.write(buf);
  61. buf.clear();
  62. }
  63.  
  64. //发送反馈给客户端
  65. buf.put("服务端接收数据成功".getBytes());
  66. buf.flip();
  67. sChannel.write(buf);
  68.  
  69. sChannel.close();
  70. outChannel.close();
  71. ssChannel.close();
  72. }
  73.  
  74. }

非阻塞式IO流

一、使用 NIO 完成网络通信的三个核心:

1. 通道(Channel):负责连接

  java.nio.channels.Channel 接口:
    |--SelectableChannel
    |--SocketChannel
    |--ServerSocketChannel
    |--DatagramChannel

    |--Pipe.SinkChannel
    |--Pipe.SourceChannel

2. 缓冲区(Buffer):负责数据的存取

3. 选择器(Selector):是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况

  1. public class TestNonBlockingNIO {
  2.  
  3. //客户端
  4. @Test
  5. public void client() throws IOException{
  6. //1. 获取通道
  7. SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  8.  
  9. //2. 切换非阻塞模式
  10. sChannel.configureBlocking(false);
  11.  
  12. //3. 分配指定大小的缓冲区
  13. ByteBuffer buf = ByteBuffer.allocate(1024);
  14.  
  15. //4. 发送数据给服务端
  16. Scanner scan = new Scanner(System.in);
  17.  
  18. while(scan.hasNext()){
  19. String str = scan.next();
  20. buf.put((new Date().toString() + "\n" + str).getBytes());
  21. buf.flip();
  22. sChannel.write(buf);
  23. buf.clear();
  24. }
  25.  
  26. //5. 关闭通道
  27. sChannel.close();
  28. }
  29.  
  30. //服务端
  31. @Test
  32. public void server() throws IOException{
  33. //1. 获取通道
  34. ServerSocketChannel ssChannel = ServerSocketChannel.open();
  35.  
  36. //2. 切换非阻塞模式
  37. ssChannel.configureBlocking(false);
  38.  
  39. //3. 绑定连接
  40. ssChannel.bind(new InetSocketAddress(9898));
  41.  
  42. //4. 获取选择器
  43. Selector selector = Selector.open();
  44.  
  45. //5. 将通道注册到选择器上, 并且指定“监听接收事件”
  46. ssChannel.register(selector, SelectionKey.OP_ACCEPT);
  47.  
  48. //6. 轮询式的获取选择器上已经“准备就绪”的事件
  49. while(selector.select() > 0){
  50.  
  51. //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”
  52. Iterator<SelectionKey> it = selector.selectedKeys().iterator();
  53.  
  54. while(it.hasNext()){
  55. //8. 获取准备“就绪”的是事件
  56. SelectionKey sk = it.next();
  57.  
  58. //9. 判断具体是什么事件准备就绪
  59. if(sk.isAcceptable()){
  60. //10. 若“接收就绪”,获取客户端连接
  61. SocketChannel sChannel = ssChannel.accept();
  62.  
  63. //11. 切换非阻塞模式
  64. sChannel.configureBlocking(false);
  65.  
  66. //12. 将该通道注册到选择器上
  67. sChannel.register(selector, SelectionKey.OP_READ);
  68. }else if(sk.isReadable()){
  69. //13. 获取当前选择器上“读就绪”状态的通道
  70. SocketChannel sChannel = (SocketChannel) sk.channel();
  71.  
  72. //14. 读取数据
  73. ByteBuffer buf = ByteBuffer.allocate(1024);
  74.  
  75. int len = 0;
  76. while((len = sChannel.read(buf)) > 0 ){
  77. buf.flip();
  78. System.out.println(new String(buf.array(), 0, len));
  79. buf.clear();
  80. }
  81. }
  82.  
  83. //15. 取消选择键 SelectionKey
  84. it.remove();
  85. }
  86. }
  87. }
  88. }

Java NIO -- 阻塞和非阻塞的更多相关文章

  1. 关于同步,异步,阻塞,非阻塞,IOCP/epoll,select/poll,AIO ,NIO ,BIO的总结

    相关资料 IO基本概念 Linux环境 同步异步阻塞非阻塞 同步与异步 阻塞与非阻塞 IO模型Reference Link 阻塞IO模型 非阻塞IO模型 IO复用模型 信号驱动异步IO模型 异步IO模 ...

  2. java网络通信:异步非阻塞I/O (NIO)

    转: java网络通信:异步非阻塞I/O (NIO) 首先是channel,是一个双向的全双工的通道,可同时读写,而输入输出流都是单工的,要么读要么写.Channel分为两大类,分别是用于网络数据的S ...

  3. 【IBM】Merlin 给 Java 平台带来了非阻塞 I/O

    Merlin 给 Java 平台带来了非阻塞 I/O 新增的功能大幅降低了线程开销 Java 技术平台早就应该提供非阻塞 I/O 机制了.幸运的是,Merlin(JDK 1.4)有一根几乎在各个场合都 ...

  4. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别参考

    参考https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral IO复用,AI ...

  5. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别(百度)

    如果面试问到IO操作,这篇文章提到的问题,基本是必问,百度的面试官问我三个问题 (1)什么是NIO(Non-blocked IO),AIO,BIO (2) java IO 与 NIO(New IO)的 ...

  6. JAVA NIO学习记录2-非阻塞式网络通信

    一.阻塞与非阻塞 传统的IO 流都是阻塞式的.也就是说,当一个线程调用read() 或write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务.因此,在完成网络通信 ...

  7. Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程

    Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程 缓冲区(Buffer) 用于存储数据 通道(Channel) 用于传输数据 多路复用器(Selector) 用于轮询 Channel 状 ...

  8. (转)IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别

    本文来自:https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral,非常感谢 ...

  9. NIO:异步非阻塞I/O,AIO,BIO

    Neety的基础使用及说明 https://www.cnblogs.com/rrong/p/9712847.html BIO(缺乏弹性伸缩能力,并发量小,容易出现内存溢出,出现宕机 每一个客户端对应一 ...

  10. Java中的阻塞和非阻塞IO包各自的优劣思考(经典)

    Java中的阻塞和非阻塞IO包各自的优劣思考 NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式. 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个 ...

随机推荐

  1. OpenBLAS简介及在Windows7 VS2013上源码的编译过程

    OpenBLAS(Open Basic Linear Algebra Subprograms)是开源的基本线性代数子程序库,是一个优化的高性能多核BLAS库,主要包括矩阵与矩阵.矩阵与向量.向量与向量 ...

  2. [清华集训2017]榕树之心[树dp]

    题意 题目链接 分析 首先解决 \(subtask3\) ,我们的策略就是进入子树,然后用其它子树来抵消,注意在子树内还可以抵消. 可以转化为此模型:有一个数列 \(a\) ,每次我们可以选定两个值 ...

  3. Nagios数据存储插件NDOUtils部署和测试

    1. 概述 NDOUTILS,Nagios Data Output Utils,Nagios数据输出工具,允许用户从Nagios导出状态和事件信息到数据库中,便于以后的检索和加工 它包括几个部分: N ...

  4. 时区提示:Local time zone must be set--see zic manual page 2018的解决办法

    问题描述:在centos服务器上执行date命令时,显示的时间信息中的时区不正常,如下: [root@ulocalhost ~]# date Mon Apr 9 02:57:38 Local time ...

  5. 矩形A + B HDU2524

    题意 给你n*m的棋盘问有多少个矩形 分析 先看只有一行或一列的情况有1+2+....+n个,因为矩形的类型有1个最小单位格子n个,2个最小单位格子n-1个,n个最小单位格子有一个 code #inc ...

  6. 转发:C#操作SQL Server数据库

    转发自:http://www.cnblogs.com/rainman/archive/2012/03/13/2393975.html 1.概述 2.连接字符串的写法 3.SqlConnection对象 ...

  7. Junit测试用例

    一.题目简介 返回一个给定整数参数的绝对值. 二.源码的github链接 https://github.com/liyan941016/test/blob/master/FileTest.java h ...

  8. I/O(输入/输出)

    1.创建引用ObjectInputStream ois =null; ObjectOutputStream oos = null; ByteArrayInputStream bais = null; ...

  9. 请求数据传入(SpringMVC)

    1.    请求处理方法签名 Spring MVC 通过分析处理方法的签名,HTTP请求信息绑定到处理方法的相应人参中. Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任 ...

  10. JQuery 操作 radio 被坑一例

    .removeAttr('checked'); .prop('checked',false); .prop('checked',true); 与 .attr("checked",t ...