linugb118--java space

Java

Java NIO---Channel部分

Java NIO---Channel部分

Channel 是连接buffer和Io设备之间的管道,当然channel也可以一头连接channel

Basic Channel Interface:
public interface Channel
{
public boolean isOpen( );
public void close( ) throws IOException;
}

1.open channel
channel作为i/o 设备的管道,分为两种,一种文件(file),另一种是端口(Socket)
file相关的只有fileChannel
socket相关的有SocketChannel, ServerSocketChannel和DatagramChannel.

socket channel可以通过factory创建新的socket channel
比如
SocketChannel sc = SocketChannel.open( );
sc.connect (new InetSocketAddress ("somehost", someport));

ServerSocketChannel ssc = ServerSocketChannel.open( );
ssc.socket( ).bind (new InetSocketAddress (somelocalport));

而fileChannel 则不能这样,他是在一个打开的andomAccessFile, FileInputStream或者FileOutputStream
对象上getChannel()
比如
RandomAccessFile raf = new RandomAccessFile ("somefile", "r");
FileChannel fc = raf.getChannel( );

2.Using Channels
三个接口:
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
{
}

需要注意的是 fileChannel 虽然也有write,read方法,但是他们能否调用write read方法是由file相关的访问权限决定的。

channel 有blocking和nonblocking两种模式,nonblocking是指永远不会将一个正在调用的线程sleep,他们被请求的结果要么
立刻完成,要么返回一个nothing的结果。
只有stream-oriented的channels(比如sockets and pipes)可以用nonblocking模式

3.Closing Channels
和buffer不一样,channel不能被重用,用完之后一定要close,此外当一个线程被设置为interrupt状态,当该线程试图访问某个channel
的话,该channel将立刻关闭。


4.Scatter/Gather
当我们在多个buffer上执行一个i/O操作的时候,我们需要将多个buffer放在一个buffer数组一并让channel来处理
Scatter/Gather interface:

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;
}

例子:
ByteBuffer header = ByteBuffer.allocateDirect (10);
ByteBuffer body = ByteBuffer.allocateDirect (80);
ByteBuffer [] buffers = { header, body };
int bytesRead = channel.read (buffers);

5.File Channels
filechannel 只能是blocking模式也就是被锁住模式,不能是nonblocking模式
public abstract class FileChannel
extends AbstractChannel
implements ByteChannel, GatheringByteChannel, ScatteringByteChannel
{
// This is a partial API listing
public abstract void truncate (long size)
public abstract void force (boolean metaData)
}
fileChannel 中有truncate和force 两个方法
truncate (long size)是以给定的size来切断file
force (boolean metaData) file属性的修改立刻影响到disk上

6.File Locking
file 锁虽然在fileChannel中提出,但是需要注意本身lock是和file相关,而且不同的操作系统提供的file也有不同,和channel无关的

public abstract class FileChannel
extends AbstractChannel
implements ByteChannel, GatheringByteChannel, ScatteringByteChannel
{
// This is a partial API listing
public final FileLock lock( )
public abstract FileLock lock (long position, long size,
boolean shared)
public final FileLock tryLock( )
public abstract FileLock tryLock (long position, long size,
boolean shared)
}

lock 有三个参数,第一个是开始锁住的file的postion, 第二个是锁住的file大小,前面这两个参数就能定义了一块lock范围,第三个是
显示lock是shared(true)类型还是exclusive(false)类型,
没有参数的lock()其实等同于fileChannel.lock (0L, Long.MAX_VALUE, false);
FileLock 本身是线程安全的,可以多个线程同时访问

tryLock() 和Lock()相似,当某个lock因为其他原因不能被获取,那么就要用tryLock() 这个时候就返回null
FileLock总关联一个特定的channel,可以通过channel()获取相关联的channel,当FileLock release(),那么对于的channel也就相应的close();

7.Memory-Mapped Files
Memory-mapped files 一般效率更高,而且因为他是和操作系统相关的,所有他不会消费jvm分配的内存
通过map()来建立MappedByteBuffer,
mapped buffers和lock有点不同,lock和产生它的channel绑定,如果channel closed那么lock也就消失
而mapped buffers本身也没有ummap方法,他是通过自身不再被引用然后被系统垃圾回收的。

8.Channel-to-Channel Transfers
channel直接的传输可以提供更好的效率

public abstract class FileChannel
extends AbstractChannel
implements ByteChannel, GatheringByteChannel, ScatteringByteChannel
{
// This is a partial API listing
public abstract long transferTo (long position, long count,
WritableByteChannel target)
Java NIO
90
public abstract long transferFrom (ReadableByteChannel src,
long position, long count)
}

这个是能在filechannel之间使用,两个socketchannel之间不能直接使用transferTo和transferFrom,但是因为socketchannel继承WritableByteChannel and ReadableByteChannel,所有可以将一个文件的内容transferTo socketChannel或直接通过transferFrom从socketChannel中读取数据

9.Socket Channels
对应以前一般一个线程对应一个socket,而在NIO中可以一个线程对应成百上千的socket,同时没有性能降低的问题
三种socket channel(DatagramChannel,SocketChannel, and ServerSocketChannel)
DatagramChannel和SocketChannel 有read和write的方法
而ServerSocketChannel 则是监听connection和创建SocketChannel,他本身不参与数据的传输
这三个channel都可以通过socket()方法获取到对应的Socket,ServerSocket,DatagramSocket
需要说明的是,socket不一样要绑定channel,通过传统的new 创建socket,那么getChannel()就会返回null

SocketChannel 有Nonblocking和blocking 两种模式
SocketChannel sc = SocketChannel.open( );
sc.configureBlocking (false); // nonblocking
...
if ( ! sc.isBlocking( )) {
doSomething (cs);
}
可以通过configureBlocking 来设置,true表示blocking mode 而false 表示nonblocking mode
对应大型应用并发处理的 建议使用nonblocking mode
看看下面的例子:
Socket socket = null;
Object lockObj = serverChannel.blockingLock( );
// have a handle to the lock object, but haven't locked it yet
// may block here until lock is acquired
synchronize (lockObj)
{
// This thread now owns the lock; mode can't be changed
boolean prevState = serverChannel.isBlocking( );
serverChannel.configureBlocking (false);
socket = serverChannel.accept( );
serverChannel.configureBlocking (prevState);
}
// lock is now released, mode is allowed to change
if (socket != null) {
doSomethingWithTheSocket (socket);
}
体验一下 blockingLock()和lock()的区别

SocketChannel 可以通过finishConnect( ),isConnectPending( ), or isConnected( )获取当前connection的状态

socket是面向流的,datagram是面向packet的
因此DatagramChannel 就是面向packet协议的channel,比如UDP/IP

10.pipe 方式 可以研究一下

 

 

 

 


 

posted on 2010-09-10 15:54 linugb118 阅读(3332) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿(1)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜