BIO,NIO,AIO学习

一、认识同步与异步

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.cnblogs.com/lqh969696/p/14656717.html