一. 网络编程的一些基础
1.先说明一下线程的挂起、阻塞、睡眠
线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状
态、阻塞状态及死亡状态。下图是使用时间片轮转法的操作系统进程的状态和它们之
间的转换。
挂起和睡眠是主动的,挂起恢复需要主动完成,睡眠恢复则是自动完成的,因为
睡眠有一个睡眠时间,睡眠时间到则恢复到就绪态。而阻塞是被动的,是在等待某种
事件或者资源的表现,一旦获得所需资源或者事件信息就自动回到就绪态。睡眠和挂
起是两种行为,阻塞则是一种状态。
挂起:一般是主动的,由系统或程序发出,甚至于辅存中去join()、wait()是挂起。
阻塞:一般是被动的,在抢占资源中得不到资源,被动的挂起在内存,等待某种资
源或信号量(即有了资源)将他唤醒。sleep()是属于阻塞。
2.同步/异步
同步和异步关注的是消息通信机制。
(1)同步:就是指在发出一个功能调用时,在没有得到结果之前,该调用就不返回。
按照这个定义,其实绝大多数函数都是同步调用。
(2)异步:概念和同步相对。 当一个异步过程调用发出后,调用者不会立刻得到结
果。实际处理这个调用的部件是在调用发出后, 通过状态、通知来通知
调用者,或通过回调函数处理这个调用。
举例:当到银行后, .可以去ATM机前排队等候 – (排队等候)就是同步等待消息 .可以去
大厅拿号,等到排到我的号时, 柜台的人会通知我轮到我去办理业务. – (等待别
人通知)就是异步等待消息。
3.阻塞/非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态(无所谓同
步或者异步,注意这里的“调用结果”就是指“2”中标黑的“调用”的结果)
(1)阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(被挂起就是阻塞,
因为是被动的)。函数只有在得到结果之后才会返回。 有人也许会把阻
塞调用和同步调用等同起来,实际上他是不同的。 对于同步调用来说,
很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
(2)非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不
会阻塞当前线程,而会立刻返回。
举例:继续上面的那个例子,不论是排队等待,还是使用号码等待通知,如果在这个
等待的过程中,等待者除了等待消息之外不能做其它的事情,那么该机制就是
阻塞的,表现在程序中,也就是该程序一直阻塞在该函数调用处不能继续往下
执行。相反,有的人喜欢在银行办理这些业务的时候一边打打电话发发短信一
边等待,这样的状态就是非阻塞的。
二. Java BIO、NIO、AIO
1.概念
(1)Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连
接请求时服务器端就需要启动一个线程进行处理,如果这个连接不
做任何事情会造成不必要的线程开销,当然可以通过线程池机制改
善。
好理解的解释:线程发起IO请求,不管内核是否准备好IO操作,从
发起请求起,线程一直阻塞,直到操作完成。
(2)Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送
的连接请求都会注册到多路复用器上,多路复用器轮询到连接有
I/O请求时才启动一个线程进行处理。
好理解的解释:线程发起IO请求,立即返回;内核在做好IO操作的
准备之后,通过调用注册的回调函数通知线程做IO
操作,线程开始阻塞,直到操作完成。
(3)Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客
户端的I/O请求都是由OS先完成了再通知服务器应用去启动
线程进行处理。
好理解的解释:线程发起IO请求,立即返回;内存做好IO操
作的准备之后,做IO操作,直到操作完成或
者失败,通过调用注册的回调函数通知线程
做IO操作完成或者失败
二. BIO、NIO、AIO的使用场景
(1)BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比
较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
(2)NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,
并发局限于应用中,编程比较复杂,JDK1.4开始支持。
(3)AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,
充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。