Java协程框架Kilim特性分析和总结

简介

Github地址

kilim 1.0:https://github.com/kilim/kilim 
kilim 2.0:https://github.com/nqzero/kilim 

特性

1.Kilim是一个Java消息传递框架,它提供了超轻量级的线程和工具,可以在这些线程之间进行快速、安全、零复制的消息传递。

2.Kilim的核心在于Mailbox跨线程共享内存,没有锁或同步,Mailbox支持多生产者,单消费者队列。

3.Kilim的Actor协程场景存在大量的处理线程,都消耗在等待后端的处理,做异步化才有意义

4.Actor采取的这种类似消息机制的方式,实际在守护线程和外部线程之间有一个队列,俗称信箱,外部线程只要把请求放入,守护线程就读取进行处理。这种异步高效方式是Actor基本原理。

5.Kilim的任务切换比Java的线程切换快出1000倍,它的消息传递比Erlang快3倍。

6.Disruptor是线程间通信最高效的方式。它可以用来替代队列,同时有很多Actors模式的特性。

疑问解答

1.Kilim中的Task,即用户线程如何调度和切换?
在多任务的调度上操作系统存在抢占式和协作式两种方式,相比传统的Thread多线程间抢占式调度,Kilim中的Task采用的是协作式调度,即由Task本身负责释放和恢复占用CPU。
2.Kilim如何识别代码中哪些方法是Pauseable,可暂停的?
通过Kilim提供的Weaver工具在代码编译后,对编译生成的字节码进行分析,识别哪些方法抛出Pauseable异常的,来判断识别方法可暂停的。
3.Kilim是如何实现线程执行过程中Task的暂停和恢复?
Kilim通过编译期字节码编织,对每一个可暂停的方法进行字节码处理,在方法执行前和执行后加上相关的执行上下文的处理:
Task暂停时将函数调用链中的当前函数的栈帧暂存到Fiber的stateStack中,并设置Fiber的isPausing为true,然后调用字节码指令return返回上层函数,而上层函数通过Fiber中的变量判断得到被调函数暂停返回,也将本函数的栈帧暂存到Fiber的stateStack中,然后也直接返回,以此类推,层层向上直至退回至WorkerThread的run方法体,这样本Task即实现暂停。
Task恢复执行是通过在暂停时将Task作为Mailbox的观察者,后续当Mailbox有接收到消息时触发观察者,在回调函数中该Task将自己再次加入到调度器Scheduler的runnableTask队列中,并唤醒工作者线程WorkerThread执行。
4.Kilim中的Weaver工具是如何针对编译的代码实现织入的?
字节码技术,具体来说通过ASM字节码框架实现对编译生成的class文件进行增强。
5.如何将一个传统的线程执行方法改造成Kilim的Task?
首先需要实现一个类继承Task,实现Task的execute方法,业务逻辑不再放在线程的run方法体体,而是放在Task的execute方法体中。
execute方法中调用的方法如果是可能暂停的,则必须声明抛出Pauseable异常,否则可以不需要抛出。
Task之间的通信通过Mailbox邮箱来传递消息,put和get时存在三种版本,包括阻塞线程,阻塞Task但不阻塞线程,非阻塞。
针对这些Task和Pauseable方法编译时,需要使用Kilim提供的Weaver工具进行编织处理,如果不进行编织处理,运行时将会异常。
对于Kilim中的方法需要注意:一个Pauseable方法只能被另一个Pauseable方法调用。
6.Kilim中哪些操作可以使得Task暂停或者恢复运行?
Task.sleep()能使当前Task暂停运行一段时间
Task.yield()能使当前Task暂停放弃运行
Task.pause()能使当前Task暂停执行
Task.resume()能使当前Task恢复执行
Mailbox.get()能使当前Task暂停执行直到Mailbox队列非空。
7.什么场景下适合应用Kilim协程?
IO密集型的应用比较适合使用协程,比如应用中存在较多的与后端的网络交互,存在较多的时间在等待后端响应,可以保证线程不会阻塞在等待网络响应,充分利用多核多线程的能力。而对于CPU密集型应用,由于大部分情况CPU都比较繁忙,Kilim不会产生很好的作用。
8.Kilim中Task和Thread之间是如何调度的?
这里直接引用Kilim官方文档中的原文来解答:

Kilim's tasks are cooperatively scheduled on a kernel thread pool. 

A Kilim task is owned and managed by a scheduler, which manages the
thread pool. When a task needs to pause, it removes itself from the
thread by popping its call stack, remembering enough about each
activation frame in order to help rebuild the stack and resume, at a
later point). The scheduler then reuses that thread for some other
task.
9.Kilim中Task占用的内存大小?
这里直接引用Kilim官方文档中的原文来解答:

The amount of memory occupied by a task is:
1. The java object that represents the task class
2. If paused, an array of activation frames is stored. The Kilim
   weaver performs data flow and live variable and constant analysis
   (intra-procedurally) to ensure that it capture only as
   much as is needed to resume.
3. The contents of all mailboxes that the task is receiving on.


参考

https://www.ibm.com/developerworks/cn/java/j-javadev2-7.html

https://blog.csdn.net/kobejayandy/article/details/18334361

https://blog.csdn.net/kobejayandy/article/details/45114671

发布了362 篇原创文章 · 获赞 144 · 访问量 110万+

猜你喜欢

转载自blog.csdn.net/FENGQIYUNRAN/article/details/103898772
今日推荐