标签:
1.同步与异步:在于多个任务和事件发生时,一个事件的发生或执行是否会导致整个流程的暂时等待
2.阻塞与非阻塞:当发出请求一个操作时,如果条件不满足,是会一直等待还是返回一个标志信息。
e.g. 读取一个文件中的内容,如果此时文件中没有内容可读,对于同步来说就是会一直在那等待,直至文件中有内容可读;而对于非阻塞来说,就会直接返回一个标志信息告知文件中暂时无内容可读。
3.IO操作包括:对硬盘的读写、对socket的读写以及外设的读写。
4.阻塞IO,非阻塞IO: IO请求操作的两个步骤:查看数据是否就绪;进行数据拷贝(内核将数据拷贝到用户线程) 区别在第一阶段:如果数据没有就绪,在查看数据是否就绪的过程中是一直等待还是直接返回一个标志信息。
Java中传统的IO都是阻塞IO,比如通过socket来读数据,调用read()方法之后,如果数据没有就绪,当前线程就会一直阻塞在read方法调 用那里,直到有数据才返回;而如果是非阻塞IO的话,当数据没有就绪,read()方法应该返回一个标志信息,告知当前线程数据没有就绪,而不是一直在那 里等待。
5. 对于同步IO:当用户发出IO请求操作之后,如果数据没有就绪,需要通过用户线程或者内核不断地去轮询数据是否就绪,当数据就绪时,再将数据从内核拷贝到用户线程;
而异步IO:只有IO请求操作的发出是由用户线程来进行的,IO操作的两个阶段都是由内核自动完成,然后发送通知告知用户线程IO操作已经完成。也就是说在异步IO中,不会对用户线程产生任何阻塞。
这是同步IO和异步IO关键区别所在,同步IO和异步IO的关键区别反映在数据拷贝阶段是由用户线程完成还是内核完成。所以说异步IO必须要有操作系统的底层支持。
阻塞IO和非阻塞IO是反映在IO操作的第一个阶段,在查看数据是否就绪时是如何处理的。
6.阻塞IO,用户线程交出CPU
1 data = socket.read();
7.非阻塞IO,用户线程不交出CPU
1 while(true){ 2 data = socket.read(); 3 if(data!= error){ 4 处理数据 5 break; 6 } 7 }
但是对于非阻塞IO就有一个非常严重的问题,在while循环中需要不断地去询问内核数据是否就绪,这样会导致CPU占用率非常高,因此一般情况下很少使用while循环这种方式来读取数据。
8.多路复用IO模型是目前使用得比较多的模型。Java NIO实际上就是多路复用IO。
有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。
在Java NIO中,是通过selector.select()去查询每个通道是否有到达事件,如果没有事件,则一直阻塞在那里,因此这种方式会导致用户线程的阻塞。
9.异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受 到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到 用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要实际的整个IO操作是如何进行的,只 需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。
异步IO是需要操作系统的底层支持,在Java 7中,提供了Asynchronous IO。
10.传统的网络服务设计模式 多线程 线程池 前者资源使用瓶颈 后者对于长连接,在一段时间内,线程池中的线程都被占用,再有连接,连接失败。
11.高性能IO设计模式:
Reactor模式(同步IO):会先对每个client注册感兴趣的事件,然后有一个线程专门去轮询每个client是否有事件发生,当有事件发生时,便顺序处理每个事件(为了提高速度,可以通过多线程或者线程池的方式处理),当所有事件处理完之后,便再转去继续轮询。
多路复用IO就是这个模式
12.Proactor模式(异步IO):当检测到有事件发生时,会新起一个异步操作,然后交由内核线程去处理,当内核线程完成IO操作之后,发送一个通知告知操作已完成,可以得知,异步IO模型采用的就是Proactor模式。
参考文献:http://www.cnblogs.com/dolphin0520/p/3916526.html
标签:
原文地址:http://www.cnblogs.com/dobestself-994395/p/4699846.html