JAVA NIO 之1

第一次接触,所以先从定义开始吧

java.nio  全程是java non-blocking IO,非阻塞型IO。根据这个段时间的学习,知道,java.IO是同步阻塞型的,每一次调用writer和read的时候,都会加锁,意味如果很多用户的话,必须排队

NIO主要有三大核心部分:Channel,Buffer,Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作。数据总是由通道读取到缓冲区,或者从缓冲区写入到通道。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此单线程可以监听多个数据通道。

NIO和传统IO的第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。

IO的各种流是阻塞的。这意味着,当一个线程调用read或write时,该线程被阻塞,直到有一些 数据被读取,或数据完全写入。该线程在此期间不能干任何事情。NIO是非阻塞模式,使一个线程从某通道发送请求读取数据,但它只能得到目前可用的数据。如果目前没有数据可用时,就什么也不会获取。而不是保持线程阻塞,所以直到数据变的可读取之前,该线程可以继续做其他的事情,非阻塞的写也是如此。线程通常将非阻塞IO空闲时间用在其他通道上执行IO操作,所以一个单独的线程在现在可以管理多个输入和输出通道(channel)。

channel,不像流,流是单向的,channel是双向的,既可以用来读,也可以用来写。

//通道表示一个实体的(硬件设备,文件,网络套接字,一个程序组件)的开放性连接,执行一个多或多个IO操作。读或写。。。
//通道要么打开,要么关闭,通道在创建的时候打开,关闭的时候关闭。
//一旦关闭。任何关于IO的操作都会抛异常
//多线程访问安全
public interface Channel extends Closeable{
    //判断通道是否打开
    public boolean isOpen();
    //关闭通道
    public void close() throws IOException;
}


buffer,buffer用于和channel进行交互,数据是从通道进入缓冲区,从缓冲区写入到通道中的 。

    实际上是一个容器,连续数组,Channel提供从文件、网络读取数据的渠道,但是读写的数据都必须经过Buffer

    一个buffer的capacity是buffer包含元素的数量,buffer的capacity是不为负且不会改变

    buffer的limit是第一个不被读或写的元素的指标,buffer的limit不为负且不能超过buffer的capacity

    buffer的position是下一个将要被读或写的元素的指标,buffer的position不为负且不能超过buffer的limit

private int mark = -1; //用于记录当前position的前一个位置或者默认是-1
private int position = 0;
private int limit;
private int capacity;

Buffer(int mark, int pos, int lim, int cap) {       // package-private
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        this.capacity = cap;
        limit(lim);
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            this.mark = mark;
        }
    }

public final Buffer limit(int newLimit) {
        if ((newLimit > capacity) || (newLimit < 0))
            throw new IllegalArgumentException();
        limit = newLimit;
        if (position > limit) position = limit;
        if (mark > limit) mark = -1;
        return this;
    }

public final Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
        position = newPosition;
        if (mark > position) mark = -1;
        return this;
    }

 向Buffer中写的数据

     从Channel中写入。。。

selector:selector运行单线程处理多个Channel。

关于FileChannel

//   是一个读取,写入,映射,和操作文件的通道
//   java.io.FileInputStream#getChannel()
//   java.io.FileOutputStream#getChannel()
//   java.io.RandomAccessFile#getChannel()

public abstract class FileChannel
    extends AbstractInterruptibleChannel
    implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel
//初始化一个新的实例 
protected FileChannel() { }

//打开或创建一个文件,返回访问文件的通道
//path 文件的路径
//options 文件打开的方式
//attrs 可选的文件属性列表
public static FileChannel open(Path path,
                                   Set<? extends OpenOption> options,
                                   FileAttribute<?>... attrs)
        throws IOException
    {
        FileSystemProvider provider = path.getFileSystem().provider();
        return provider.newFileChannel(path, options, attrs);
    }

//从通道中读取一个字节序列到ByteBuffer中
/每写读次,ByteBuffer 中的positon都会更新,大小为positon + n
//其中 n  = ByteBuffer.limit,若最后一次,就是最后一次读取的byte的数目
public abstract int read(ByteBuffer dst) throws IOException;

//从通道中读取字节序列到指定的ByteBuffer数组
public abstract long read(ByteBuffer[] dsts, int offset, int length)
        throws IOException;

public final long read(ByteBuffer[] dsts) throws IOException {
        return read(dsts, 0, dsts.length);
    }
//Bytes 从该通道的当前文件位置开始读取字节,然后使用实际读取的字节数更新文件位置。

//从给定的buffer中,向通道中写一序列字节
//每写一次,ByteBuffer 中的positon都会更新,大小为positon + n
//其中 n  = ByteBuffer.limit,若最后一次,就是最后一次读取的byte的数目
public abstract int write(ByteBuffer src) throws IOException;

//从给定的buffer[]中,从offset开始,读取length字节,向通道中写入
 public abstract long write(ByteBuffer[] srcs, int offset, int length)
        throws IOException;

 public final long write(ByteBuffer[] srcs) throws IOException {
        return write(srcs, 0, srcs.length);
 }

//返回通道中文件的位置
public abstract long position() throws IOException;
//设置通道中文件的位置
public abstract FileChannel position(long newPosition) throws IOException;
//返回当前通道中文件的大小(实时)
public abstract long size() throws IOException;
//将此通道的文件截取为指定大小
public abstract FileChannel truncate(long size) throws IOException;
//将字节从此通道的文件传输到给定的可写字节通道。
public abstract long transferTo(long position, long count,
                                    WritableByteChannel target)
        throws IOException;
。。。。。。。。。。。。。
public class JavaNio {
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream("E:\\sourcecode\\hello.txt");
        FileChannel inChannel = ((FileInputStream) in).getChannel();
        OutputStream out = new FileOutputStream("E:\\sourcecode\\hello1.txt");
        FileChannel outChannel = ((FileOutputStream) out).getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(2);
        while((inChannel.read(byteBuffer))!=-1){
            byteBuffer.flip();
            if(byteBuffer.hasRemaining()){
                outChannel.write(byteBuffer);
            }
            byteBuffer.compact();
        }
        out.close();
        in.close();
    }
}

//分配一个新的字节缓冲区。
public static ByteBuffer allocate(int capacity) {
        if (capacity < 0)
            throw new IllegalArgumentException();
        return new HeapByteBuffer(capacity, capacity);
    }

HeapByteBuffer(int cap, int lim) {            // package-private

        super(-1, 0, lim, cap, new byte[cap], 0);
    }

/***************************************************
buf.clear();          // Prepare buffer for use
while (in.read(buf) >= 0 || buf.position != 0) {
    buf.flip();
    out.write(buf);
    buf.compact();    // In case of partial write
}
***************************************************/

public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

public final boolean hasRemaining() {
        return position < limit;
    }

猜你喜欢

转载自blog.csdn.net/qq_35815781/article/details/85242265
今日推荐