我准备战斗到最后,不是因为我勇敢,是我想见证一切。 --双雪涛《猎人》
[TOC]
Thinking
- 一个技术,为什么要用它,解决了那些问题?
- 如果不用会怎么样,有没有其它的解决方法?
- 对比其它的解决方案,为什么最终选择了这种,都有何利弊?
- 你觉得项目中还有那些地方可以用到,如果用了会带来那些问题?
- 这些问题你又如何去解决的呢?
本文基于Netty 4.1.45.Final-SNAPSHOT
1、简述
Channel是JDK 1.4之后引入的NIO中非常重要的一个概念,所有的I/O操作必须通过Channel进行读写,不能直接操作缓冲区Buffer。(这里需要提醒的一点就是,Channel是双向的,既可以从通道中读取数据,又可以写数据到通道。)
那么Java NIO 中的通道(Channel)于传统BIO中的文件流有那些异同呢?
- Channel即可以读取数据,又可以向里写数据。但是流的读写通常是单向的。
- 通道可以异步地读写。
- 通道中地数据总是要先读到一个Buffer中,或者总是要从一个Buffer中写入。
上述操作如图所示:
Channel通道双向读写数据.png
2、Channel
java.nio.channels.Channel
2.1、源码
public interface Channel extends Closeable {
/**
* Tells whether or not this channel is open.
判断此通道是否处于打开状态
*
* @return <tt>true</tt> if, and only if, this channel is open
*/
public boolean isOpen();
/**
* Closes this channel.
关闭此通道
*
* <p> After a channel is closed, any further attempt to invoke I/O
* operations upon it will cause a {@link ClosedChannelException} to be
* thrown.
*关闭通道后,
任何进一步尝试在其上调用I / O 的操作都会导致抛出{@link ClosedChannelException}
* <p> If this channel is already closed then invoking this method has no
* effect.
如果此通道已关闭,则调用此方法无效
*
* <p> This method may be invoked at any time. If some other thread has
* already invoked it, however, then another invocation will block until
* the first invocation is complete, after which it will return without
* effect. </p>
可以随时调用此方法。但是,如果某个其他线程已经调用了它,
则另一个调用将被阻塞,直到第一个调用完成为止,之后它将返回而没有任何效果
就是在该Method 调用后,还是可以被调用的,但是如果此方法正在被调用,该操作是会被阻塞的。
之后调用不会返回任何东西。
*
* @throws IOException If an I/O error occurs
*/
public void close() throws IOException;
}
Channel有非常多的实现,其中有四个非常重要的类
2.2、类图
Channel类图.png- FileChannel :从文件中读写数据。
- DatagramChannel :通过UDP读写网络中的数据。
- SocketChannel :通过TCP读写网络中的数据。
- ServerSocketChannel : 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
2.3、示例
/**
* Channel 示例
* <p>
* 使用FileChannel 读取文件 基于Buffer
*
* @author by Mr. Li
* @date 2020/2/10 22:08
*/
@Slf4j
public class ChannelExample {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile("E:/idea_workspace/springcloud2.0/netty/netty-mytest/src/main/resources/data/nio-data.txt", "rw");
FileChannel channel = file.getChannel();
// 获取 缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
int read = channel.read(buf);
while (read != -1) {
log.info("Read Ended ,Message:{}", read);
// 数组反转,才能读取
buf.flip();
while (buf.hasRemaining()) {
log.info("Message:{}", buf.get());
}
// 清空缓冲区
buf.clear();
read = channel.read(buf);
}
file.close();
}
}
本文仅供笔者本人学习,一起进步!
——努力努力再努力xLg
加油!
网友评论