同步 异步
- 指两个线程间的关系
- 两个线程之间要么是同步的,要么是异步的
- 同步操作时,调用者需要等待被调用者返回结果,才会进行下一步操作
- 异步操作时,调用者不需要等待被调用者返回调用,即可进行下一步操作
- 被调用者通常依靠事件、回调等机制来通知调用者结果
阻塞 非阻塞
- 是对同一个线程来说的
- 在某个时刻,线程要么处于阻塞状态,要么处于非阻塞状态
- 关注的是程序在等待调用结果(消息,返回值)时的状态
- 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回
- 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程
类比
- 打电话向旅馆前台预定房间
- 第一次打占线(阻塞)
- 第二次打接通,前台说“先别挂电话,我在系统里查一下”(同步)
- 我可以一直等着(阻塞),也可以放下电话去喝个水再回来(非阻塞)
- 前台说“我先查一下,待会找到了通知你”(异步)
- 我肯定不会一直等了(非阻塞)
BIO NIO AIO
- IO(同步阻塞)
- 面向流,单向传输
- 阻塞IO和非阻塞IO的区别在于第一步发起IO请求是否会被阻塞
- 同步IO和异步IO的区别就在于第二个步骤是否阻塞(操作系统做完IO操作再将结果返回给你)
- 两个阶段
- 数据准备阶段
- 内核空间复制数据到用户进程缓冲区(用户空间)阶段
- BIO(同步阻塞)
- 基于 IO+Socket 就可以编写一个最基本的BIO服务器
- 一个连接一个线程
- 通常有一个acceptor(消费者) 去负责监听客户端的连接
- 它接收到客户端的连接请求之后为每个客户端创建一个线程进行链路处理,处理完成之后,线程销毁
- 并发量比较大的情况下,系统会创建大量的线程
- 从而导致服务器线程暴增,性能急剧下降,甚至宕机
- 在JDK1.4之前,用Java编写网络请求,都是建立一个ServerSocket
- 客户端建立 Socket 时就会询问是否有线程可以处理,如果没有,要么等待,要么被拒绝
- NIO(同步非阻塞)
- 一个请求一个线程
- 基于事件驱动思想,解决BIO的大并发问题
- IO操作准备好时再通知线程
- 客户端同时和多个服务器进行通讯,必须使用多线程处理
- 即将每一个客户端请求分配给一个线程来单独处理
- 由缓冲区(Buffers)、通道(Channels)和非阻塞I/O的核心类组成
- 客户端发送的连接请求都会注册到多路复用器上
- 多路复用器轮询到连接有I/O请求时才启动一个线程进行处理
- AIO(异步非阻塞)
- 一个有效请求一个线程
- IO操作已经完成后,再向线程发出通知(触发回调函数)
- 异步IO采用“订阅-通知”模式
- 应用程序向操作系统注册IO监听,然后继续做自己的事情
- 操作系统发生IO事件,并且准备好数据后,在主动通知应用程序,触发相应的函数
- 读写操作
- 当进行读写操作时,只须直接调用API的read或write方法
- 对于读操作,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序
- 对于写操作,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序
- read/write方法都是异步的,完成后会主动调用回调函数
参考
彻底理解同步 异步 阻塞 非阻塞
https://www.cnblogs.com/loveer/p/11479249.html
漫谈Java IO之普通IO流与BIO服务器
https://www.cnblogs.com/xing901022/p/8666147.html
Java BIO、NIO与AIO的介绍
https://www.cnblogs.com/wobushitiegan/p/12596351.html
Java核心(五)深入理解BIO、NIO、AIO
http://www.imooc.com/article/265871
BIO和NIO了解多少呢?一起从实践角度重新理解下吧