前面已经准备好了greenlet对应的Java版本了,一个删减后的kilim(http://segmentfault.com/blog/taowen/1190000000697487)。接下来,就看怎么用协程来实现异步io了。首先,拿一段最最简单的tcp socket accept的代码:
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9090));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("listening...");
selector.select();
scheduler.accept(serverSocketChannel);
System.out.println("hello");
这里使用的是java 6的NIO1的selector模型。直接拿NIO的原始api写代码会死人的。引入协程就是为了把上下连续的业务逻辑放在一个协程里,把与业务关系不大的selector的处理部分放到框架的ioloop里。也就是把一段交织的代码,分成两个关注点不同的组成部分。
改造之后的代码在这里: https://github.com/taowen/daili/tree/1e319f929678213a8d8f63ee5e8b8cf016637317
这是改造之后的效果:
Scheduler scheduler = new Scheduler();
DailiTask task = new DailiTask(scheduler) {
@Override
public void execute() throws Pausable, Exception {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9090));
serverSocketChannel.configureBlocking(false);
System.out.println("listening...");
scheduler.accept(serverSocketChannel);
System.out.println("hello");
}
};
scheduler.callSoon(task);
scheduler.loop();
其中最关键的一行是 scheduler.accept(serverSocketChannel); 这个调用是阻塞的。但是只阻塞调用它的Task协程。如果有多个Task并行的话,别的Task可以在这个时候被运行。那么scheduler.accept是如何做到把NIO的selector api转换成这样的形式的呢?
public SocketChannel accept(ServerSocketChannel serverSocketChannel) throws IOException, Pausable {
SocketChannel socketChannel = serverSocketChannel.accept();
if (null != socketChannel) {
return socketChannel;
}
SelectionKey selectionKey = serverSocketChannel.keyFor(selector);
if (null == selectionKey) {
selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, new WaitingSelectorIO());
} else {
selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_ACCEPT);
}
WaitingSelectorIO waitingSelectorIO = (WaitingSelectorIO) selectionKey.attachment();
waitingSelectorIO.acceptBlockedAt = System.currentTimeMillis();
waitingSelectorIO.acceptTask = (Task) Task.getCurrentTask();
selectionKey.attach(waitingSelectorIO);
Task.pause(waitingSelectorIO);
return serverSocketChannel.accept();
}
这个函数分成四部分:第一部分是尝试去accept,如果有戏就不用NIO了。第二部分是注册selection key,说明我希望知道什么时候可以accept了,并把task作为附件加上去。第三部分是Task.pause放弃掉执行权。第四部分是task被回调了,说明等待的accept已经ok了,可以去调用了。
但是Task.pause了之后,是谁在把这个暂停的task重新拉起来执行的呢?这个就是scheduler的loop干的活了
public void loop() throws IOException {
while (true) {
executeReadyTasks();
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey selectionKey : selectionKeys) {
WaitingSelectorIO waitingSelectorIO = (WaitingSelectorIO) selectionKey.attachment();
if (selectionKey.isAcceptable()) {
Task taskToCall = waitingSelectorIO.acceptTask;
waitingSelectorIO.acceptBlockedAt = 0;
waitingSelectorIO.acceptTask = null;
callSoon(taskToCall);
}
}
}
}
在循环中调用selector.select获得网络事件的通知。如果selection key就绪了,就把附件里的task取出来回调。具体的回调发生在executeReadyTasks内部,其实就是调用一下resume而已。
private void executeReadyTasks() {
Task task;
while((task = readyTasks.poll()) != null) {
executeTask(task);
}
}
private void executeTask(Task task) {
try {
task.resume();
} catch (Exception e) {
LOGGER.error("failed to execute task: " + task, e);
}
}
这样一个只能接收telnet 127.0.0.1 9090打印一行hello的异步io应用就写好了。
http://segmentfault.com/a/1190000000700227
相关推荐
基于java的开发源码-异步IO框架 Cindy.zip 基于java的开发源码-异步IO框架 Cindy.zip 基于java的开发源码-异步IO框架 Cindy.zip 基于java的开发源码-异步IO框架 Cindy.zip 基于java的开发源码-异步IO框架 Cindy.zip ...
对于协程,Kotlin协程库提供了丰富的API,如`launch`, `async`, `suspend`函数等,用于构建异步流程和控制协程的行为。 文件"**xiecheng**"可能包含了关于线程与协程实际应用的示例代码或者性能测试结果。为了...
同步IO 是指应用程序在执行IO 操作时,需要等待IO 操作完成后才能继续执行其他操作,而异步IO 则是指应用程序可以继续执行其他操作,而不需要等待IO 操作完成。 在本文中,我们将讨论基于系统底层通信技术Socket 的...
这里我们将深入探讨同步IO、异步IO、阻塞IO和非阻塞IO的概念,理解它们的工作原理以及在实际应用中的差异。 1. 同步IO与异步IO: - **同步IO**:在同步模式下,应用程序执行I/O操作时会等待操作完成。这意味着程序...
本项目为基于Python的gtornado异步IO设计源码,共计包含26个文件,包括19个Python源文件、2个Markdown文件、1个.gitignore文件、1个YAML文件、1个LICENSE文件、1个文本文件、1个SQL文件。该源码旨在实现tornado框架...
最后,异步IO(非阻塞IO)和协程是Python并发编程的高级主题。Python的asyncio库提供了一种事件驱动的编程模型,通过async/await关键字实现协程,可以实现高效的并发执行,特别适用于I/O密集型任务。理解事件循环、...
本项目的目标是根据Kotlin的协程设计理念,为Java开发者提供一个简单实现的协程库,并同时提供Kotlin和Java两个版本。 首先,我们要理解Kotlin协程的基本概念。协程是一种轻量级的线程,它们不是真正的线程,但可以...
JAVA源码异步IO框架CindyJAVA源码异步IO框架Cindy
1. **WSAAsyncSelect**:这是WinSock异步IO模型的一种实现方式,它允许应用程序指定一个窗口句柄,当特定的网络事件发生时,Windows会发送一个消息到该窗口。例如,当有新的数据到达时,将发送一个FD_READ消息。应用...
java资源异步IO框架 Cindyjava资源异步IO框架 Cindy提取方式是百度网盘分享地址
在标题所提及的“基于异步IO的socket通信程序”中,我们可以推测有以下三个主要部分: 1. **Socket通信的抽象**:这是对socket通信的基本封装,通常包含连接建立、数据传输和断开连接等基本操作。抽象类或接口可以...
总之,Java的异步IO框架Cindy为开发者提供了一个高效、易用的工具,帮助他们构建出能够应对高并发场景的应用。通过理解和掌握Cindy,开发者能够更好地利用Java平台的优势,提升软件系统的性能和响应能力。
"异步IO模型编程实例(纯C语言)" 异步IO模型是指在进行IO操作时,不会阻塞当前线程或进程,而是将IO操作交由操作系统或专门的IO处理线程处理,从而提高系统的并发性和响应速度。在Windows平台上,异步IO模型主要...
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non...
Python 携程_异步IO 11协程停止.mp4
Python 携程_异步IO 05定义协程.mp4
通过研究这个"基于Java的实例源码-异步IO框架 Cindy.zip",开发者不仅可以掌握Java NIO的基本概念,还能深入了解异步编程和事件驱动模型,为构建高效、可扩展的Java应用程序打下坚实基础。同时,通过对比不同异步...
Python 携程_异步IO 01协程的概念.mp4
本篇文章将深入探讨Java中的异步IO框架Cindy,揭示其设计原理、核心组件以及如何在实际项目中应用。 首先,我们来理解一下什么是异步I/O。与传统的同步I/O模式不同,异步I/O不会在等待数据读写完成时阻塞线程,而是...