基本概念
同步:被调用者未处理完请求之前,调用不返回,调用者会一直等待结果的返回。
异步:调用者无需等待被调用者返回,返回之前可以做其他事情,被调用者处理完后,通过回调或者其他方式通知调用者。
阻塞:等待条件就绪后,才会往下执行,否则当前线程挂起。
非阻塞:无需等待条件就绪,可以干其他的事情。条件就绪后再去处理它。
NIO和IO的区别
NIO即New IO,NIO库是在 JDK 1.4 中引入的。
(1)I/O 与 NIO 最重要的区别是数据打包和传输的方式:IO是面向流(Stream)的,NIO是面向块(buffer)的:
面向流(Stream):IO流是没有缓存的概念,每次从流中一个一个字节的去读,而且只能顺序从流中读取数据,如果需要处理已读的字节,则需要把已读字节缓存。面向流的 I/O 通常相当慢。想象成水管,水流按顺序流动。
面向块(buffer):面向块的处理方式是先把数据读到缓冲区,按需要决定是否需要开始处理数据,增加了处理过程的灵活性,但还是需要判断缓冲区中是否包含了所需处理的全部数据,在这期间,你可以去做其他事情。按块处理数据比按流处理数据要快得多。
(2)阻塞与非阻塞:
BIO是阻塞的,accept、read、write都是阻塞的。水管前面的水流堵住了,那么后面的水流也不会流动,会堵塞住。
NIO是非阻塞的,可以判断当前Buff中是否有数据可读或者准备好,没有数据或者数据没准备好,则不会堵塞,可以做其他事情。前面是准备读,真正读写Buffer的时候依然是阻塞的。
(3)使用方式上的不同:NIO使用较BIO更为复杂,尤其使用JDK原生NIO的API,大多数使用netty。包括Selector选择器、通道 Channel、缓冲区Buffer管理(后面详细讲解)。
(4)Selector选择器:一个Selector可以同时管理多个Channel,Selector选择器不同的系统底层实现不一样,windows用select,linux用epoll。有必要提一句Selector的一个bug。我们通过轮训来获得相应的事件,这里有可能会产生空轮训,导致CPU100%,netty的做法是根据时间判断,在一定的时间内空轮训次数大于500次,然后重建Selector。