阻塞和非阻塞:
阻塞:
1、相关的方法都是阻塞的,相当于线程是暂停的,暂停期间不占用CPU;
2、如果服务端只有一个线程,多个客户端连接到服务端,阻塞方法之间相互影响导致不能正常工作,所以有多个客户端就会在服务端创建多个线程,当客户端比较多时会造成服务器压力太大,如果客户端连接后不做读写操作会导致线程堵塞、浪费资源;
3、也可以使用线程池,如果客户端只是连接服务端后而不做操作,导致线程池中的线程一直被占用着,其他的客户端也无法访问,所以使用线程池只适合短链接;
非阻塞:
1、服务器不断进行轮询看是否游客户端的 连接请求获读写请求,即使没有客户端的请求也会一直空转,造成CPU的浪费;
多路复用:
客户端连接服务端成功后生成一个channel对象,这个channel注册到多路复用器selector上,然后由selector对象监听客户端的读写请求,selector是阻塞的,当收到客户端的请求时即放开阻塞处理客户端的请求,一个selector可以注册多个channel,也就是说在服务端一个线程可以响应多个客户端的连接;
nio的三大组件:channel、buffer、selector
buffer:客户端和服务端之间传输的数据,客户端和服务端传递的数据经过序列化后通过字节数组的方式传输;
channel:客户端和服务端创建连接后的通道,数据就在这个通道中传输;
selector:多路复用器,在服务端一个selector中可以注册多个channel,selector会监听channel中的请求事件,将请求的事件指派给handler处理后通过channel返回给客户端,实现了一个线程处理多个客户端的请求,selector中提供了阻塞和非阻塞方法,阻塞是将线程阻塞等到有请求的时候就处理请求(如select方法),非阻塞是根据方法的返回值判断是否有请求事件(如selectNow方法);
事件发生后能否不处理
事件发生后,要么处理,要么取消(cancel),不能什么都不做,否则下次该事件仍会触发
同步和异步:
同步:当一个线程向服务端发起请求后,返回的结果任然是这个线程处理,就是同步;
异步:当一个线程向服务端发起请求后,返回的结果任然是另外的线程处理,就是异步;
所以区分同步和异步就看接收返回结果的线程和发起请求的线程是不是同一个线程,对于同步和异步的解释五花八门,以这个解释为准;
零拷贝:
当服务端接收到一个请求时,请求的数据首先是到 网卡 然后是到系统内存、再然后到jvm的内存中,通过jvm中的应用程序处理后将结果 发到cocket缓冲区再通过网关发给客户端;
ByteBuffer提供了两种实现:HeapByteBuffer和 DirectByteBuffer
HeapByteBuffer 是堆内存,也就是jvm内存
DirectByteBuffer 直接内存,也就是直接使用的系统内存,不需要再将数据从系统内存拷贝到jvm内存中,这种情况就叫做零拷贝;