一、认识同步与异步
1、同步,异步是指应用程序和内核的相互交互而言的
同步:是指用户进程触发io操作等待或者轮训的方式查看io操作是否就绪
异步:异步调用发出调用之后,不会立刻得到结果,而是通过被调用者通知调用者,或者回调函数处理调用。
二、阻塞和非阻塞
阻塞和非阻塞是针对于进程访问数据的时候,根据IO状态采取不同方式
阻塞:读写操作一直等待,
非阻塞:读写会返回一个状态值,进行下一步
例:
洗衣服逻辑:
1、洗衣服,一直在旁边等着洗衣机洗衣服,然后晾干——同步阻塞
2、洗衣服,洗衣机在洗衣服,自己去做饭,时不时看一下衣服洗好了没有——同步非阻塞
3、洗衣服,一直在旁边等着洗衣机洗衣服,然后晾干——异步阻塞
4、洗衣服,洗衣机在洗衣服,自己去做饭,衣服洗好了没有——异步非阻塞
三、BIO的了解
同步阻塞IO,服务器实现模式为一个连接一个线程。
即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
例: 服务端:
public class IOServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("127.0.0.1",8081));
while (true){
Socket socket = serverSocket.accept();
new Thread(()->{
try {
byte[] bytes = new byte[1024];
int len = socket.getInputStream().read(bytes);
System.out.println(new String(bytes,0,len));
socket.getOutputStream().write(bytes,0,len);
socket.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
客户端:
public class IOClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",8081);
socket.getOutputStream().write("hello".getBytes());
socket.getOutputStream().flush();
System.out.println("server send back data =====");
byte[] bytes = new byte[1024];
int len = socket.getInputStream().read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
}
}
四、NIO的了解
同步非阻塞IO (non-blocking IO / new io)是指JDK 1.4 及以上版本
服务器实现模式为一个请求一个通道。
即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。
通道(Channels):NIO 新引入的最重要的抽象是通道的概念。Channel 数据连接的通道。数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中 。
缓冲区(Buffers):通道channel可以向缓冲区Buffer中写数据,也可以像buffer中存数据。
选择器(Selector):使用选择器,借助单一线程,就可对数量庞大的活动 I/O 通道实时监控和维护。
当一个连接创建后,不会需要对应一个线程,这个连接会被注册到多路复用器,所以一个连接只需要一个线程即可,所有的连接需要一个线程就可以操作,该线程的多路复用器会轮训,发现连接有请求时,才开启一个线程处理。
NIO模型中selector的作用,一条连接来了之后,现在不创建一个while死循环去监听是否有数据可读了,而是直接把这条连接注册到selector上,然后通过检查这个selector,就可以批量监测出有数据可读的连接,进而读取数据。
例:客户端
public class NIOClient {
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1",8888);
SocketChannel channel = null;
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
channel = SocketChannel.open();
channel.connect(address);
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("客户端即将给 服务器发送数据..");
String line = sc.nextLine();
if(line.equals("exit")){
break;
}
buffer.put(line.getBytes("UTF-8"));
buffer.flip();
channel.write(buffer);
buffer.clear();
int readLen = channel.read(buffer);
if(readLen == -1){
break;
}
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
System.out.println("收到了服务器发送的数据 : "+ new String(bytes,"UTF-8"));
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != channel){
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
五、AIO的了解
异步非阻塞IO。A代表asynchronize。
当有流可以读时,操作系统会将可以读的流传入read方法的缓冲区,并通知应用程序,对于写操作,OS将write方法的流写入完毕是操作系统会主动通知应用程序。因此read和write都是异步 的,完成后会调用回调函数。
使用场景:连接数目多且连接比较长(重操作)的架构,比如相册服务器。重点调用了OS参与并发操作,编程比较复杂。Java7开始支持。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13010.html