`
airu
  • 浏览: 270762 次
  • 性别: Icon_minigender_1
  • 来自: 云南
社区版块
存档分类
最新评论

JavaNIO-通道

 
阅读更多
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的介绍了。这次就到这里。
2
12
分享到:
评论

相关推荐

    JAVA-NIO-DEMO

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心特点是非阻塞,这使得在处理大量并发I/O请求时更为高效。...

    nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio

    在Java NIO中,数据是以通道(Channels)和缓冲区(Buffers)的形式进行传输,而不是直接通过流。这种设计使得NIO能够同时处理多个输入/输出操作,从而实现多路复用。 标题“nio.rar_NIO_NIO-socket_java nio_java ...

    java-NIO-demo

    Java NIO(Non-blocking Input/Output)是一种在Java中处理I/O操作的新方式,相比于传统的BIO( Blocking I/O),NIO提供了更高效的数据传输能力,尤其在处理大量并发连接时。NIO的核心概念包括通道(Channels)、...

    Java-NIO-Programming-Cookbook(含源码)

    Java NIO(非阻塞I/O)编程是Java平台中的一种高效I/O处理方式,相比传统的BIO(阻塞I/O),NIO提供了更灵活、性能更高的数据传输机制。本书《Java NIO Programming Cookbook》旨在深入浅出地介绍如何利用Java NIO...

    java网络编程NIO视频教程

    Java NIO-Channel-Socket通道-概述 - **主要内容**:介绍Socket通道的基础知识,包括SocketChannel和ServerSocketChannel。 - **学习目标**:理解Socket通道的基本概念和使用场景。 #### 8. Java NIO-Channel-...

    httpcore-nio-4.3.jar包

    Java NIO(New IO)是Java 1.4引入的一套新的I/O API,替代了传统的BIO(Blocking IO)。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。通道可以读写数据,缓冲区用于临时存储数据,...

    Java_NIO-Selector.rar_java nio_selector

    Selector是Java NIO框架中的核心组件,它使得单个线程能够管理多个通道(Channels),从而提高系统资源利用率并优化性能。下面我们将详细探讨Java NIO中的Selector机制。 1. **Selector的作用** Selector的主要功能...

    java-NIO-入门教程.docx

    "Java NIO 入门教程" Java NIO(New I/O)是 Java 语言中的一种新的输入/输出机制,自 JDK 1.4 开始引入。不同于传统的面向流的 I/O,NIO 采用面向块的 I/O 方式,提供了高速的 I/O 操作。NIO 库的主要特点是使用...

    JavaNIO chm帮助文档

    Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六) Selector Java NIO系列教程(七) FileChannel Java NIO系列教程(八) SocketChannel Java NIO系列教程(九) ServerSocketChannel Java NIO...

    java NIO 视频教程

    Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。 ...

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    [第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...

    Java NIO英文高清原版

    NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据量的系统。Netty是一个基于NIO的高性能、异步事件驱动的网络应用框架,它简化了网络编程,广泛应用于服务器端应用开发。 ...

    Java语言基础教程-Java NIO流篇2

    本教程将深入讲解Java NIO中的流和通道概念,以帮助开发者更好地理解和利用这一强大的功能。 首先,我们要理解Java NIO的核心组件之一——流。在Java的IO体系中,流是数据传输的抽象,它代表了数据的流向,可以是...

    java NIO.zip

    Java NIO支持多种类型的通道,包括文件通道(FileChannel)、套接字通道(SocketChannel)和服务器套接字通道(ServerSocketChannel)等。通道可以同时进行读写操作,并且可以实现异步读写。 2. **缓冲区(Buffers...

    java-instantcode-developing.rar_java nio

    Java NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。在本压缩包"java-instantcode-developing.rar_java nio"中,主要探讨的是如何使用Java NIO来开发应用程序。 1. **通道(Channel)**...

    基于matrix-nio和nio-template构建的管理员和个人协助.zip

    Matrix-NIO和NIO-Template是两个用于网络编程的开源库,主要应用于Java环境中,用于提高服务器端的I/O性能和处理能力。Matrix-NIO是一个轻量级的、高性能的网络通信框架,它利用Java NIO(非阻塞I/O)技术来实现高效...

    【IT十八掌徐培成】Java基础第27天-04.NIO-Selector-Server-Client.zip

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的I/O操作方式。传统的IO模型基于阻塞IO,即当进行读写操作时,如果数据未准备好,程序会一直等待,...

    java-nio.rar_NIO_java nio

    传统的Java I/O基于字节流和字符流,而NIO则提供了通道(Channels)和缓冲区(Buffers)的概念,以及非阻塞I/O操作的能力。本资料"java-nio.rar"主要探讨的是如何使用Java NIO实现异步连接池,这在高并发场景下尤其...

    socket-nio-single-reactor.zip

    Socket NIO 单 Reactor 模式是一种在 Java 中实现高性能网络编程的技术,它结合了非阻塞I/O(New I/O,即NIO)和Reactor设计模式。本示例代码旨在帮助开发者理解如何使用Java NIO和Reactor模式构建网络服务。尽管...

Global site tag (gtag.js) - Google Analytics