美文网首页
JAVA NIO Channels(二)使用Channel

JAVA NIO Channels(二)使用Channel

作者: ShootHzj | 来源:发表于2017-08-19 14:55 被阅读123次

    先看如下的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异常。另外,如果线程被设置为中断状态,然后线程尝试获取一个通道,通道就会立刻关闭,抛出同样的异常。

    相关文章

      网友评论

          本文标题:JAVA NIO Channels(二)使用Channel

          本文链接:https://www.haomeiwen.com/subject/kartdxtx.html