以下所有IO模型均指网络IO
BIO
Blocking IO(阻塞IO)
首先说 Linux , 在Linux kernel内核中,阻塞IO是什么?为什么称为阻塞IO?优缺点以及怎么使用?
1、在Linux中,一个服务端 要和外部应用程序 进行网络通信,需要进行三步操作,accept()接收一个返回客户端整型值(阻塞操作,若没有客户端连接,会一直进行等待),bind()绑定accept返回的客户端整型值,listener()监听客户端数据,在监听状态下,会调用系统内核receive()进行数据接收(阻塞操作,若客户端一直没有数据发送,会一直进行等待)。
2、在Java程序中,使用new serverSocket();即 当前应用 会主动向CPU 发起中断操作,CPU通过参数 去调用 系统内核程序,即上述1所阐述程序。因此java程序的BIO仍然依赖于 操作系统的内核程序,即Linux kernel
BIO解释:在上述网络通信的 过程中,有两处阻塞操作,在我们的Java编程模型中,一般第一处阻塞操作会启动一个主线程,然后一直等待新的客户端的连接,对于第二处阻塞操作来说,当有一个客户端链接过来时,我们会启动一个线程 去进行数据接收,而在这个子线程中,接收数据的receive操作是阻塞的。
在上述的Java编程模型实现的BIO下,Linux kernel中,第二次阻塞中,有 C10K的问题,当一万个客户端连接过来,需要启动一万个线程去处理,会浪费资源,而且单位时间内,系统中断后,CPU大量的时间浪费在了调度读取客户端数据的程序上,影响性能
回答主题的三个问题:
1、阻塞IO是什么?上述即是传统的BIO操作,即blocking IO (阻塞IO)。
2、为什么称为阻塞IO? 因为有两处阻塞操作,根据你的客户端编程语言的实现,当有一处是单线程处理,而客户端没有连接或者数据,线程即会一直进行阻塞等待。因此称为阻塞IO。
3、优缺点?缺点:当客户端连接过多,影响性能和浪费资源。优点:单线程处理,当机器性能足够时,速率快。 何时用?若不存在高并发的连接,可以考虑使用BIO。
NIO
linux kernel Non-blocking IO(linux内核非阻塞IO )
什么是No-blocking IO 非阻塞IO?为什么称为非阻塞?优缺点及何时用?
1、通过上述的BIO的缺点,我们可以发现,IO阻塞 依赖于Linux内核的实现,因此,内核不进行改变,仍然是阻塞模式。因此,Linux提供了另外一种IO 模型。又称为非阻塞IO。
即是上述 三步 操作:accept、bind、listener-> receive 进行了改进。当accept等待客户端连接时。 如果此时没有客户端连接 ,则立即返回-1。并不会进行阻塞,如果有客户端连接 ,则会返回一个客户端的socket整型值。同样,receive操作也一样,如果没有数据
进行接收,则会立即返回-1.。不会进行阻塞。这样的IO模型称之为NIO,非阻塞IO。要使用非阻塞IO,可以在调用方法内核方法accept时候,参数传递No-blocking。即可实现非阻塞。
Java New IO(Java New IO)
2、有了上述的 内核的改进。应用程序 在调用内核的时候,就有了新的方法。Java在此基础上提供了新的API进行调用,即成为Java New IO。注意,低版本1.4的 JDK不支持进行非阻塞IO的调用。在Java的编程模型中。要使用非阻塞IO,
同样需要注意:当前的accept已经不会进行阻塞,因此 要在主线程中 设置 循环调用,当没有 客户端连接的时候,会返回null,则进行下一次循环,当有一个 客户端连接时,即可以将 客户端 放置集合中,再在 主线程 内部进行循环遍历 所有的 客户端,调用receive,在Java中即
是read()方法进行 数据读取,若读取到数据,则对数据进行处理,若没有数据接收,则内部循环继续,对下一个客户端进行处理。
回答主题的三个问题:
1、什么是非阻塞IO?上述即是传统的No-blocking IO 非阻塞IO,在Java中 又称为Java NewIO。
2、为什么称为非阻塞IO? 因为两处阻塞操作accept 和 receive,已经不会进行阻塞,若没有连接或者数据接收,内核会返回-1,在Java NewIO中会返回null,没有数据时会返回-1 。
3、优缺点?缺点:当客户端连接过多,C10K问题,一万个客户端连接,只有一个客户端有数据,那么在这种编程模型下,会有9999此无用的循环,浪费性能。
优点:解决了阻塞问题,避免了线程创建过多的资源开销,CPU频繁调度降低性能。 何时用?若连接甚多,切都有数据IO,可以进行使用。