我会看看这个: http : //www.chiark.greenend.org.uk/~sgtatham/coroutines.html ,它非常有趣,应该提供一个好地方开始。 但是,我们当然使用Java,所以我们可以做得更好(或者更糟,因为没有macros)
根据我对协程的理解,你通常有一个生产者和一个消费者协同程序(或者至less这是最常见的模式)。 但是从语义上讲,你不希望制片人打电话给消费者,反之亦然,因为这会引起不对称。 但是鉴于基于堆栈的语言的工作方式,我们需要有人来打电话。
所以这是一个非常简单的types层次结构:
public interface CoroutineProducer { public T Produce(); public boolean isDone(); } public interface CoroutineConsumer { public void Consume(T t); } public class CoroutineManager { public static Execute(CoroutineProducer prod, CoroutineConsumer con) { while(!prod.IsDone()) // really simple { T d = prod.Produce(); con.Consume(d); } } }
当然,难点在于实现接口,特别是难以将计算分解成单独的步骤。 为此,您可能需要一整套其他持久控制结构 。 基本的想法是,我们想要模拟非本地控制转移(最后它有点像我们模拟goto )。 我们基本上希望通过将当前操作的状态保持在堆而不是在堆栈pc使用堆栈和pc (程序计数器)。 因此,我们将需要一堆辅助类。
例如:
假设在一个理想的世界中,你想写一个看起来像这样的消费者(psuedocode):
boolean is_done; int other_state; while(!is_done) { //read input //parse input //yield input to coroutine //update is_done and other_state; }
我们需要像is_done和other_state一样抽象局部variables,并且我们需要抽象出while循环,因为我们的yield类操作不会使用堆栈。 所以我们来创build一个while循环抽象和关联的类:
enum WhileState {BREAK, CONTINUE, YIELD} abstract class WhileLoop { private boolean is_done; public boolean isDone() { return is_done;} private T rval; public T getReturnValue() {return rval;} protected void setReturnValue(T val) { rval = val; } public T loop() { while(true) { WhileState state = execute(); if(state == WhileState.YIELD) return getReturnValue(); else if(state == WhileState.BREAK) { is_done = true; return null; } } } protected abstract WhileState execute(); }
这里的基本技巧是将局部variables移动到类variables,并将范围块转换为类,这使得我们能够在得到返回值后重新input我们的“循环”。
现在来执行我们的制作人
public class SampleProducer : CoroutineProducer { private WhileLoop loop;//our control structures become state!! public SampleProducer() { loop = new WhileLoop() { private int other_state;//our local variables become state of the control structure protected WhileState execute() { //this implements a single iteration of the loop if(is_done) return WhileState.BREAK; //read input //parse input Object calcluated_value = ...; //update is_done, figure out if we want to continue setReturnValue(calculated_value); return WhileState.YIELD; } }; } public Object Produce() { Object val = loop.loop(); return val; } public boolean isDone() { //we are done when the loop has exited return loop.isDone(); } }
其他基本的控制stream程结构也可以采用类似的技巧。 你最好build立一个这些帮助类的库,然后用它们来实现这些简单的接口,最终会给你的协同例程的语义。 我敢肯定,我在这里写的所有内容都可以概括和扩展。