BIO、NIO、AIO概述

一、BIO、NIO、AIO概述

1、BIO:(同步 + 阻塞) BlockIO
2、NIO:(同步 + 非阻塞)Non-Block——JDK 1.4开始

【注】NIO之所以是同步的,是因为它的accept/read/write方法的内核I/O操作都会阻塞当前线程,下面会讲解NIO的三个主要组成部分:Buffer(缓冲区);Channel(通道);Selector(选择器)。

3、AIO:(异步 + 非阻塞)Asynchronous——JDK1.7开始

二、什么是阻塞、非阻塞、同步、异步:

1、阻塞:等待结果,等待期间,什么也不可以做;
2、非阻塞:等待结果,等待期间,可以做其他事情;
3、同步:主动获取结果;
4、异步:等待通知结果。

组合(拿在照相馆等待照片为例子):
1、同步 + 阻塞:

  举个例子:我们在照相馆等待打印照片的时候,什么也不可以做,只能等待商家把照片洗完,期间会不停的问老板照片洗完没有,老板不会主动告诉你,这个过程就叫同步阻塞。

2、同步 + 非阻塞

  举个例子:我们在照相馆等待照片的时候,可以玩手机,可以看电视,可以问老板洗完没有,同样,老板不会主动告诉你,这个过程就叫同步非阻塞;

3、异步 + 阻塞:

  举个例子:我们不用在照相馆等待,得去照相馆外面的板凳上等待,当照相馆的照片打印好,老板会主动通知你,在外面等待的期间,你不可以干任何事情,这个过程叫异步阻塞;

4、异步 + 非阻塞

  举个例子:我们不用在照相馆等待,可以去外面等待,等待的时候,我们可以去逛商场,看电影,照片洗完之后,老板会通知你,这个过程叫异步非阻塞。

三、NIO的三个主要组成部分(Buffer(缓冲区)、Channel(通道)、Selector(选择器))

1、Buffer(缓冲区)概述:

(1)jar包:java.nio.Buffer(抽象类):用于特定原始类型(基本类型)的数据的容器。
(2)子类:

1、ByteBuffer:里面可以封装一个byte[]数组;
2、ShortBuffer:里面可以封装一个short[]数组;
3、CharBuffer:里面可以封装一个char[]数组;
4、IntBuffer:里面可以封装一个int[]数组;
5、LongBuffer:里面可以封装一个long[]数组;
6、FloatBuffer:里面可以封装一个float[]数组;
7、DoubleBuffer:里面可以封装一个double[]数组。

(3)因为ByteBuffer比较重要,下面我们主要以他为例,进行代码示范:

1)因为ByteBuffer是一个抽象类,所以不能通过构造方法区创建ByteBuffer对象,所以我们需要使用它的静态方法来获取ByteBuffer对象:

下面是它的三个静态方法:

   1、public static ByteBuffer allocate(int capacity):使用一个“容量”来创建一个“间接字节缓存区”——在“堆”空间中创建;
 示范代码: ByteBuffer byteBuffer = ByteBuffer.allocate(10);
   创建一个初始容量为10的byteBuffer[]数组,里面每个元素的初始值为0;
   2、public static ByteBuffer allocateDirect(int capacity);使用一个“容量”来创建一个“直接字节缓冲区”——在系统内存中创建;
   示范代码:ByteBuffer byteBuffer = ByteBuffer.allcateDirect(10);
   创建一个初始容量为10的byteBuffer[]数组,里面每个元素的初始值为0;
   3、public static ByteBuffer wrap(byte[] byteArray):使用一个“byte[]数组”创建一个“间接字节缓冲区”;
   示范代码:byte[] bytes = {1,2,,3,4,5};
                     ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
   创建一个初始容量为字符长度的,元素为byte[]数组元素相对应的ByteBuffer[]数组。
   【注意:】ByteBuffer容量一旦确定,不可改变。

下面来介绍它的成员方法:

 1、public ByteBuffer put(byte b):向当前可用位置添加数据;
 2、public ByteBuffer put(byte byteArray):向当前可用位置添加一个byte[]数组;【注意数组长度不能超过ByteBuffer[]当前位置到最后的长度】
 3、public ByteBuffer put(byte[] byteArray,int offset,int len);添加一个byte[]数组的一部分;
 4、byte[] arry();获取此缓冲区的byte[]数组;

示范代码:

import java.nio.ByteBuffer;
import java.util.Arrays;

public class Demo01 {
    public static void main(String[] args) {
        //通过ByteBuffer中的静态方法allocate()来创建一个长度为10的ByteBuffer对象;
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        //通过ByteBuffer中的put()方法,添加数据:
        byteBuffer.put((byte)10);
        byteBuffer.put((byte)20);
         //通过get()方法来获取ByteBuffer数组,通过String的构造方法,将其转换成字符串。
        System.out.println(Arrays.toString(byteBuffer.array()));//[10, 20, 0, 0, 0, 0, 0, 0, 0, 0]
        //通过ByteBuffer中的put(byte[] byteArr)添加数据
        byte[] bytes = {1,2,3,4};
        byteBuffer.put(bytes);
        //通过get()方法来获取ByteBuffer数组,通过String的构造方法,将其转换成字符串。
        System.out.println(Arrays.toString(byteBuffer.array()));//[10, 20, 1, 2, 3, 4, 0, 0, 0, 0]
        //通过ByteBuffer中的put(byte[] byteArr,int offset,int len)添加数据
        byteBuffer.put(bytes,0,2);
         //通过get()方法来获取ByteBuffer数组,通过String的构造方法,将其转换成字符串。
        System.out.println(Arrays.toString(byteBuffer.array()));//[10, 20, 1, 2, 3, 4, 1, 2, 0, 0]

    }
}

5、get(int index):获取缓冲区中指定索引处的元素:

实例代码(与上面的代码连接):

        System.out.println(byteBuffer.get(0));//10
        System.out.println(byteBuffer.get(1));//20
        System.out.println(byteBuffer.get(2));//1
        System.out.println(byteBuffer.get(3));//2
6、int capacity();返回Buffer所能包含的元素的最大数量;

示范代码:

System.out.println(byteBuffer.capacity());//10
7、public int limit();获取此缓冲区的限制;
8、public Buffer limit(int newLimit);设置此缓冲区的限制
示范代码:
       System.out.println(byteBuffer.limit());//10
        byteBuffer.limit(5);
        System.out.println(byteBuffer.limit());//5
9、public int position();获取当前可写入位置索引;
10、public Buffer position(int p);更改当前可写入位置索引;
public class Demo06position {
  public static void main(String[] args) {
    //创建一个长度为10的ByteBuffer
    ByteBuffer buffer = ByteBuffer.allocate(10);//     p
    System.out.println(Arrays.toString(buffer.array()));//[0, 0, 0, 0, 0, 0,
0, 0, 0, 0]
    System.out.println(buffer.position());//0索引
    buffer.put((byte)10);//往position=0索引添加数据
    buffer.put((byte)20);//往position=1索引添加数据
    buffer.put((byte)30);//往position=2索引添加数据          p
    System.out.println(Arrays.toString(buffer.array()));//[10, 20, 30, 0, 0,
0, 0, 0, 0, 0]
    System.out.println(buffer.position());//3索引
    //更改position的位置为1
    buffer.position(1);//                    p
    System.out.println(Arrays.toString(buffer.array()));//[10, 20, 30, 0, 0,
0, 0, 0, 0, 0]
    buffer.put((byte)100);//往position=1索引添加数据
    buffer.put((byte)101);//往position=2索引添加数据
    System.out.println(Arrays.toString(buffer.array()));//[10, 100, 101, 0,
0, 0, 0, 0, 0, 0]
 }
}
11、public Buffer clear():还原缓冲区的状态;
     将position设置为:0
     将限制limit设置为容量capacity;
     丢弃标记mark;
public class Demo07clear {
  public static void main(String[] args) {
    ByteBuffer buffer = ByteBuffer.allocate(10);
8.缩小范围-flip
public Buffer flip():缩小limit的范围。 获取读取的有效数据0到position之间的数据
将limit设置为当前position位置; [10, 11, 12, 0, 0, 0, 0, 0, 0, 0] position=3 limit=10
将当前position位置设置为0; position=0 limit=3 new String(bytes,0,len)
丢弃标记。
    System.out.println(Arrays.toString(buffer.array()));//[0, 0, 0, 0, 0, 0,
0, 0, 0, 0]
    buffer.put((byte)10);//往position=0索引添加数据
    buffer.put((byte)20);//往position=1索引添加数据
    buffer.put((byte)30);//往position=2索引添加数据
    buffer.limit(5);//                         p  
l
    System.out.println(Arrays.toString(buffer.array()));//[10, 20, 30, 0, 0,
0, 0, 0, 0, 0]
    System.out.println("限定:"+buffer.limit()+"位置:"+buffer.position());//限:5位置:3
    buffer.clear();
    System.out.println("限定:"+buffer.limit()+"位置:"+buffer.position());//限:10位置:0
 }
}
12、public Buffer flip():缩小limit的范围,获取读取的有效数据0到position之间的数据
     将limit设置为当前position的位置;
     将当前position位置设置为0;
     丢弃标记
public class Demo02 {
    public static void main(String[] args) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        byteBuffer.put((byte)1);
        byteBuffer.put((byte)2);
        byteBuffer.put((byte)3);
        byteBuffer.put((byte)4);
        byteBuffer.put((byte)5);
        System.out.println("容量:" + byteBuffer.capacity() + ";限制:" + byteBuffer.limit() + ";当前位置:" + byteBuffer.position());//容量:10;限制:10;当前位置:5
        byteBuffer.flip();
        System.out.println("容量:" + byteBuffer.capacity() + ";限制:" + byteBuffer.limit() + ";当前位置:" + byteBuffer.position());//容量:10;限制:5;当前位置:0
    }
}

2、Channel(通道)概述:

Channel表示通道;
分类:文件通道:FileChannel
网络通道:SocketChannel和ServerSocketChannel

ServerSocketChannel和SocketChannel创建连接:
获取对象的方式:使用静态方法open

   static ServerSocketChannel open() 打开服务器插槽通道;

成员方法:

  客户端:
  1、ServerSocketChannel bind(SocketAddress local):给服务器绑定指定的端口号,小括号里面的直接new
  2、SocketChannel accept()监听客户端的请求;
  3、SelectableChannel configureBlocking(boolean block);设置服务器的阻塞模式 【true 阻塞;false 不写默认使阻塞的】
  服务器:
  1、
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值