Channel
这里的Channel接口很细。一个Channel能做什么呢?
package java.nio.channels; public interface Channel {
public boolean isOpen( );
public void close( ) throws IOException;
}
很简单吧。这个也太抽象了。通道就是这样。其实和我们看到的管道一样。可以关闭,可以问,这个管道通不通?
当然,最主要的还是我们如何使用呢?读和写永远是两个孪生操作。
对一个管道的字节读,有 ReadableByteChannel, WritableByteChannel,和
InterruptibleChannel。 有了这三个接口,我们的管道就成型了。
然后,接下来的接口便是 ByteChannel 之类的。ByteChannel类继承了ReadableByteChannel和WritableByteChannel的属性。然后还有很多很多的Channel了。例如:SocketChannel,FileChannel,ServerSocketChannel等等。
那么,如何打开一个管道呢。
打开一个管道,通常就是创建一个管道。这里,如果是SocketChannel,我们可以直接使用open方法,如果是FileChannel,则需要在一个已经打开的文件上使用。例如:RandomAccessFile, FileInputStream, FileOutputStream上调用 getChannel()方法。
管道打开,接下来就是读写管道。根据ReadableByteChannel和WritableByteChannel接口来看。
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
{}
这下,可以和我们之前的缓冲区结合起来了。注意,管道只和ByteBuffer打交道。
这里还要注意,SocketChannel和FileChannel都是实现了以上三个接口的。那么,也就是说,他们都有读写的方法,但是对于FileChannel来说,并非如此,因为有的文件可能是只读的,那么,如果调用write方法的,就会抛出NonWritableChannelException异常。
下面看一个简单的例子。
package shaoxin.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class ChannelCopy {
public static void main(String []args) throws Exception{
ChannelCopy copyc = new ChannelCopy();
ReadableByteChannel readChannel = Channels.newChannel(System.in);
WritableByteChannel writeChannel = Channels.newChannel(System.out);
copyc.copyChannel(readChannel, writeChannel);
readChannel.close();
writeChannel.close();
}
public void copyChannel(ReadableByteChannel from ,WritableByteChannel to)
throws Exception{
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.flip();
while(from.read(buffer)!=-1){
buffer.flip();
to.write(buffer);
buffer.compact();
}
buffer.flip();
while(buffer.hasRemaining()){
to.write(buffer);
}
}
public void copyChannel2(ReadableByteChannel from ,WritableByteChannel to)
throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(from.read(buffer)!=-1){
buffer.flip();
while(buffer.hasRemaining()){
to.write(buffer);
}
buffer.clear();
}
}
}
这个例子中,我们又看到一种Channel的创建方法,使用Channels的newChannel方法来包装一个流。这里的copyChannel有两种方法。第一种,使用compact来压缩,可以减少系统调用,对于后一种,则是每次都吧缓冲区中的数据写入管道。这种方法可能会导致更多的IO调用。大家可以自己思考为什么。
这里还有些特性没讲。例如阻塞和非组塞,还有非阻塞和Selector一起使用,可以实现多路复用(multipluxed I/O)。这些都在后面有介绍。
关闭一个通道调用close。注意这可能引起系统阻塞。因为通道关闭底层的I/O的线程可能阻塞。多次调用close没有关系。第一个阻塞后面的close,后面的close如果发现通道已经关闭就直接返回。
这里复杂的是引入InterruptibleChannel。如果一个实现了InterruptibleChannel的接口的通道,在一个线程上阻塞了,并切这个线程被中断(调用interrupt()),那么这个通道被关闭,并且这个线程产生一个ClosedByInterruptException异常。
中断往往是通过一个中断标志来标记的。如果一个被标记为中断的线程,试图访问一个通道,那么同样抛出ClosedByInterruptException异常。
使用 Thread.interrupted()可以清除中断标志。
这个设计看起来很严格,实际上也是为了跨平台的实现设计的。因为不可能在不同平台上要求对中断后的通道产生一直可靠的I/O操作。
这样的设计,也说明了,可中断的通道是可以异步关闭的。如果有其他的线程在等待改通道,那么通道关闭时,将会给所有等待的线程唤醒并抛出一个AsynchronousCloseException异常。
一般来说,不实现InterruptibleChannel的通道都是不进行底层代码实现的特殊通道,他们永不阻塞。
接下来,可能要啰嗦一段。那就是为了提高I/O性能,我们有时候可能要组合多个缓冲区,或者从多个缓冲区读数据。这时,Scatter和Gather就登场了。
public interface ScatteringByteChannel extends ReadableByteChannel
{
public long read (ByteBuffer [] dsts) throws IOException;
public long read (ByteBuffer [] dsts, int offset, int length) throws IOException;
}
public interface GatheringByteChannel extends WritableByteChannel
{
public long write(ByteBuffer[] srcs) throws IOException;
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
}
看到这两个接口,我们就一下明白了吧。
还是copy一个片段例子来看看。假设这个channel是一个有48个字节的socketChannel
ByteBuffer header = ByteBuffer.allocateDirect (10);
ByteBuffer body = ByteBuffer.allocateDirect (80);
ByteBuffer [] buffers = { header, body };
int bytesRead = channel.read (buffers);
那么,首先把header填充满10个字节,然后剩余38个字节就是body的了。
然后我们可能这样使用:
switch (header.getShort(0)) {
case TYPE_PING:
break;
case TYPE_FILE:
body.flip( );
fileChannel.write (body);
break;
default:
logUnknownPacket (header.getShort(0), header.getLong(2), body);
break;
}
这里直接使用body来处理,是不是很方便呢。
好了。下面将是FileChannel和SocketChannel的介绍了。这次就到这里。
分享到:
相关推荐
Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心特点是非阻塞,这使得在处理大量并发I/O请求时更为高效。...
在Java NIO中,数据是以通道(Channels)和缓冲区(Buffers)的形式进行传输,而不是直接通过流。这种设计使得NIO能够同时处理多个输入/输出操作,从而实现多路复用。 标题“nio.rar_NIO_NIO-socket_java nio_java ...
Java NIO(Non-blocking Input/Output)是一种在Java中处理I/O操作的新方式,相比于传统的BIO( Blocking I/O),NIO提供了更高效的数据传输能力,尤其在处理大量并发连接时。NIO的核心概念包括通道(Channels)、...
Java NIO(非阻塞I/O)编程是Java平台中的一种高效I/O处理方式,相比传统的BIO(阻塞I/O),NIO提供了更灵活、性能更高的数据传输机制。本书《Java NIO Programming Cookbook》旨在深入浅出地介绍如何利用Java NIO...
Java NIO-Channel-Socket通道-概述 - **主要内容**:介绍Socket通道的基础知识,包括SocketChannel和ServerSocketChannel。 - **学习目标**:理解Socket通道的基本概念和使用场景。 #### 8. Java NIO-Channel-...
Java NIO(New IO)是Java 1.4引入的一套新的I/O API,替代了传统的BIO(Blocking IO)。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。通道可以读写数据,缓冲区用于临时存储数据,...
Selector是Java NIO框架中的核心组件,它使得单个线程能够管理多个通道(Channels),从而提高系统资源利用率并优化性能。下面我们将详细探讨Java NIO中的Selector机制。 1. **Selector的作用** Selector的主要功能...
"Java NIO 入门教程" Java NIO(New I/O)是 Java 语言中的一种新的输入/输出机制,自 JDK 1.4 开始引入。不同于传统的面向流的 I/O,NIO 采用面向块的 I/O 方式,提供了高速的 I/O 操作。NIO 库的主要特点是使用...
Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六) Selector Java NIO系列教程(七) FileChannel Java NIO系列教程(八) SocketChannel Java NIO系列教程(九) ServerSocketChannel Java NIO...
Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。 ...
[第4节] JavaNIO流-通道1.flv [第5节] Java NIO流-通道2.flv [第6节] Java NIO流-socket通道操作.flv [第7节] Java NIO流-文件通道操作.flv [第8节] Java NIO流-选择器 .flv [第9节] Java NIO流-选择器操作.flv...
NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据量的系统。Netty是一个基于NIO的高性能、异步事件驱动的网络应用框架,它简化了网络编程,广泛应用于服务器端应用开发。 ...
本教程将深入讲解Java NIO中的流和通道概念,以帮助开发者更好地理解和利用这一强大的功能。 首先,我们要理解Java NIO的核心组件之一——流。在Java的IO体系中,流是数据传输的抽象,它代表了数据的流向,可以是...
Java NIO支持多种类型的通道,包括文件通道(FileChannel)、套接字通道(SocketChannel)和服务器套接字通道(ServerSocketChannel)等。通道可以同时进行读写操作,并且可以实现异步读写。 2. **缓冲区(Buffers...
Java NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。在本压缩包"java-instantcode-developing.rar_java nio"中,主要探讨的是如何使用Java NIO来开发应用程序。 1. **通道(Channel)**...
Matrix-NIO和NIO-Template是两个用于网络编程的开源库,主要应用于Java环境中,用于提高服务器端的I/O性能和处理能力。Matrix-NIO是一个轻量级的、高性能的网络通信框架,它利用Java NIO(非阻塞I/O)技术来实现高效...
Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的I/O操作方式。传统的IO模型基于阻塞IO,即当进行读写操作时,如果数据未准备好,程序会一直等待,...
传统的Java I/O基于字节流和字符流,而NIO则提供了通道(Channels)和缓冲区(Buffers)的概念,以及非阻塞I/O操作的能力。本资料"java-nio.rar"主要探讨的是如何使用Java NIO实现异步连接池,这在高并发场景下尤其...
Socket NIO 单 Reactor 模式是一种在 Java 中实现高性能网络编程的技术,它结合了非阻塞I/O(New I/O,即NIO)和Reactor设计模式。本示例代码旨在帮助开发者理解如何使用Java NIO和Reactor模式构建网络服务。尽管...