很長一段時間,我都很天真的認爲python,特別是以gevent爲表明的庫,纔是協程的樂土。Java裏是無法實現協程,更別說實現stackless python這樣能夠pickle的協程的。Bong!咱真的是太井底之蛙了。
Java不但能夠實現協程,並且還有不少個實現版本。不徹底列表以下:html
還有一個據(做者)說是最NB的kilim (https://github.com/kilim/kilim)
這些協程庫的實現方式都是相似的,都是經過jvm字節碼生成達到pause/resume的目的。在這篇文章中,RIFE的做者很清楚地講明白了其實現方式:
http://www.artima.com/lejava/articles/continuations.htmljava
Geert Bevin: At the byte-code level, when the method pops variables
from the stack, exactly the same operation will be performed on the
parallel stack. We just add a piece of byte code that mimics what goes
on exactly. Then, when a continuation has to be resumed, there's a bit
of added byte-code that interacts with the state of the stack, and
puts all the variables in the correct location so that they are
present when the executing thread passes that point. At this point,
it's as if nothing happened—execution resumed as if nothing happened.python
The second problem is how to arrive at the point to resume a
continuation. You want to skip over code that you don't want to
execute. That's easily done in byte code, because you can maintain a
tableswitch in byte code that allows you to jump to a particular
location. You can create a unique label for each continuation point,
jump to that label in the switch table, and then you know exactly what
the stack for that label of variables was. You can restore that stack,
and continue executing from that point on.git
kiliam的做者用代碼解釋得更加清楚(http://www.malhar.net/sriram/kilim/thread_of_ones_own.pdf):github
// original void a() throws Pasuable { x = ... b(); // b is pausable print (x); }
通過代碼加強以後是web
// transformed code void a(Fiber f) { switch (f.pc) { // prelude case 0: goto START; case 1: goto CALL_B} START: x = ... CALL_B: // pre_call f.down() b(f); f.up() // post-call switch (f.status) { case NOT_PAUSING_NO_STATE: goto RESUME case NOT_PAUSING_HAS_STATE: restore state goto RESUME case PAUSING_NO_STATE : capture state, return case PAUSING_HAS_STATE: return } RESUME: print (x); }
由於這些框架都是以java對象的方式來存儲call stack state和programe counter的,因此要作到序列化存儲一個執行中的狀態(continuation)一點都不困難。RIFE在其web框架就狠狠地利用了clonable的狀態來實現複雜的wizard(回到任意時刻地過去從新執行之類的)。
看過了這些實現以後,我不由以爲持久化一個continuation好像沒啥了不得的,爲何會是stackless python的pypy兩家的獨門絕技呢?基於CPython的兩個協程實現,一個greenlet一個fibers是否能夠實現狀態的持久化?狀態持久化能不能不用更高效的serializer來實現呢?apache