欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA NIO Channels(二)使用Channel

程序员文章站 2022-04-24 12:38:42
...

先看如下的API

public interface ReadableByteChannel extends Channel {
  public int read (ByteBuffer dst) throws IOException;
}
public interface WritableByteChannel extends Channel {
  public int write(ByteBuffer src) throws IOException;
}
public interface ByteChannel extends ReadableByteChannel, WritableByteChannel {
}

通道可以是双向的也可以是单向的。根据需要实现这三个接口中的一个。

通道的read(),write()方法都以ByteBuffer作为参数,每个都返回操作了的字节数,并更新ByteBuffer中的position属性。
下面的例子展示了使用channel进行putget的基本操作

    public static final int BUFFER_SIZE = 16*1024;

    public static void main(String[] args) throws IOException {

        ReadableByteChannel source = Channels.newChannel(System.in);
        WritableByteChannel dest = Channels.newChannel(System.out);
        //call one of copy method
        source.close();
        dest.close();
    }

    public static void channelCopy1 (ReadableByteChannel src, WritableByteChannel dest) throws IOException{
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        while (src.read(buffer)!=-1) {
            //准备好数据
            buffer.flip();

            //向通道中写入数据,可能阻塞
            dest.write(buffer);

            //调用compact方法,可以确保数据都被dest处理
            buffer.compact();
        }
        //还有可能有数据剩余,此时只是没有可读数据了而已
        while (buffer.hasRemaining()) {
            dest.write(buffer);
        }
        buffer.clear();
    }

    public static void channelCopy2 (ReadableByteChannel src, WritableByteChannel dest) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        while (src.read(buffer)!=-1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                dest.write(buffer);
            }
            buffer.clear();
        }
    }

通道可以工作在阻塞或者非阻塞模式下。如果工作在非阻塞模式下,调用它的线程永远不会sleep。请求操作要么立刻完成,要么返回结果表明没有进行任何操作。只有面向流的通道,像socket或者pipe才可以工作在非阻塞模式。

跟buffer不同,channel不可以被复用。一个打开的通道代表着跟特定IO服务之间的连接,还封装着连接的状态。当通道关闭的时候,连接丢失。调用通道的close方法会导致当关闭IO服务的时候,线程短暂地阻塞,就算工作在非阻塞模式也一样。对同一个通道调用多次close方法是无害的。如果第一个线程在close方法中阻塞,其他调用close方法的线程也会阻塞等待。后面的close方法什么都不做,然后立刻返回。

通道有一些和关闭中断相关的特性。如果一个通道实现了InterruptibleChannel接口。那么,如果线程正在被通道所阻塞,然后线程被中断,通道会被关闭,然后线程会收到一个ClosedByInterruptException异常。另外,如果线程被设置为中断状态,然后线程尝试获取一个通道,通道就会立刻关闭,抛出同样的异常。