1、引言关于Java网络编程中的同步IO和异步IO的区别及原理的文章非常的多,具体来说主要还是在讨论Java BIO和Java NIO这两者,而关于Java AIO的文章就少之又少了(即使用也只是介绍了一下概念和代码示例)。 在深入了解AIO之前,我注意到以下几个现象:
Java AIO的这些不合常理的现象难免会令人心存疑惑。所以决定写这篇文章时,我不想只是简单的把AIO的概念再复述一遍,而是要透过现象,深入分析、思考和并理解Java AIO的本质。 2、我们所理解的异步
public
void
create() {
//TODO
}
public
void
build() {
executor.execute(() -> build());
}
不管是用
@Async注解,还是往线程池里提交任务,他们最终都是同一个结果,就是把要执行的任务,交给另外一个线程来执行。
这个时候,我们可以大致的认为,所谓的“异步”,就是用多线程的方式去并行执行任务。 3、Java BIO和NIO到底是同步还是异步?Java BIO和NIO到底是同步还是异步,我们先按照异步这个思路,做异步编程。 3.1BIO代码示例
InputStream in = socket.getInputStream();
in.read(data);
// 接收到数据,异步处理
executor.execute(() -> handle(data));
public
void
handle(
byte
[] data) {
// TODO
}
如上:BIO在
read()时,虽然线程阻塞了,但在收到数据时,可以异步启动一个线程去处理。
3.2NIO代码示例
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while
(iterator.hasNext()) {
SelectionKey key = iterator.next();
if
(key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
executor.execute(() -> {
try
{
channel.read(byteBuffer);
handle(byteBuffer);
}
catch
(Exception e) {
}
});
}
}
public
static
void
handle(ByteBuffer buffer) {
// TODO
}
同理:NIO虽然
read()是非阻塞的,通过
select()可以阻塞等待数据,在有数据可读的时候,异步启动一个线程,去读取数据和处理数据。
3.3产生的理解偏差此时我们信誓旦旦地说,Java的BIO和NIO是异步还是同步,取决你的心情,你高兴给它个多线程,它就是异步的。 但果真如此么? 在翻阅了大量博客文章之后,基本一致的阐明了——BIO和NIO是同步的。 那问题点出在哪呢,是什么造成了我们理解上的偏差呢? 那就是参考系的问题,以前学物理时,公交车上的乘客是运动还是静止,需要有参考系前提,如果以地面为参考,他是运动的,以公交车为参考,他是静止的。 Java IO也是一样,需要有个参考系,才能定义它是同步还是异步。 既然我们讨论的是关于Java IO是哪一种模式,那就是要针对IO读写操作这件事来理解,而其他的启动另外一个线程去处理数据,已经是脱离IO读写的范围了,不应该把他们扯进来。 3.4尝试定义异步所以以IO读写操作这事件作为参照,我们先尝试的这样定义,就是:发起IO读写的线程( 调用read和write的线程),和实际操作IO读写的线程,如果是同一个线程,就称之为同步,否则是异步。 按上述定义:
|
首页 上一页 1 2 3 4 下一页 尾页 1/4/4 | |
【大 中 小】【打印】 【繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部】 | |
上一篇:Nacos源码 (5) Grpc服务端和客户端 | 下一篇:ThreadLocal:线程中的全局变量 |