用Java实现协程
这个问题与我有关Java中现有协程实现的问题有关。如我所怀疑的,如果事实证明Java中尚没有完整的协程实现,那么实现这些协程将需要什么?
正如我在该问题中所说的,我了解以下内容:
- 您可以将“协程”实现为后台的线程/线程池。
- 您可以在后台使用JVM字节码来完成棘手的事情,以使协程成为可能。
- 所谓的“达芬奇机” JVM实现具有使协程在无需字节码操作的情况下就可以实现的原语。
- 也有多种基于JNI的协程方法。
我将依次解决每个人的不足之处。
回答:
这种“解决方案”是病态的。协程的整个目的是 避免
线程,锁定,内核调度等开销。协程应该轻巧,快速,并且只能在用户空间中执行。根据具有严格限制的全倾斜线程来实现它们会失去所有优势。
回答:
该解决方案更实用,尽管很难实现。这大致相当于跳入C语言中的协程库的汇编语言(这是其中的多少个),其优点是您只需要担心一种架构就可以了。
除非您可以找到在不兼容的堆栈上执行相同操作的方法,否则,这将使您只能在完全兼容的JVM堆栈上运行代码(例如,这意味着没有Android)。但是,如果确实找到了解决方法,那么您现在已经将系统复杂性和测试需求提高了一倍。
回答:
达芬奇机很适合实验,但是由于它不是标准的JVM,因此它的功能不会在任何地方都可用。实际上,我怀疑大多数生产环境都将特别禁止使用达芬奇机器。因此,我可以用它来进行出色的实验,但不能用于我希望发布到现实世界中的任何代码。
这也具有类似于上面的JVM字节码操作解决方案的附加问题:在替代堆栈(如Android的堆栈)上将不起作用。
回答:
这种解决方案完全没有用Java来做到这一点。CPU和操作系统的每种组合都需要独立的测试,并且每一个都是潜在的令人沮丧的细微故障点。另外,当然,我可以将自己完全束缚在一个平台上,但这也使得在Java中做事情完全没有意义。
所以…
不使用这四种技术之一,是否可以用Java实现协程?还是我会被迫使用气味最小的那四种(JVM操作)中的一种?
编辑添加:
只是为了确保避免混淆,这是 与_我的另一个 _相关的 问题,但并非相同。为了避免不必要地重新发明轮子,那个人正在寻找
实现。这个问题是一个问题,如果另一个问题无法解决,如何在Java中实现协程。目的是在不同的线程上保留不同的问题。
回答:
我来看一下:http :
//www.chiark.greenend.org.uk/~sgtatham/coroutines.html,它非常有趣,应该提供一个不错的起点。但是我们当然使用Java,所以我们可以做得更好(或者可能更糟,因为没有宏:))
根据我对协程的了解,您通常会有一个 和一个
协程(或者至少这是最常见的模式)。但是从语义上讲,您不希望生产者致电消费者,反之亦然,因为这会引入不对称性。但是考虑到基于堆栈的语言的工作方式,我们将需要有人来进行调用。
因此,这是一个非常简单的类型层次结构:
public interface CoroutineProducer<T>{
public T Produce();
public boolean isDone();
}
public interface CoroutineConsumer<T>
{
public void Consume(T t);
}
public class CoroutineManager
{
public static Execute<T>(CoroutineProducer<T> prod, CoroutineConsumer<T> con)
{
while(!prod.IsDone()) // really simple
{
T d = prod.Produce();
con.Consume(d);
}
}
}
当然,现在最困难的部分是 实现 接口,特别是很难将计算分为几个步骤。为此,您可能需要其他整套
。基本思想是我们要模拟控件的非本地传递(最后,它有点像在模拟goto
)。我们基本上希望pc
通过将当前操作的状态保留在堆中而不是堆栈中来摆脱使用堆栈和(程序计数器)的麻烦。因此,我们将需要一堆帮助程序类。
例如:
假设在一个理想的世界中,您想要编写一个看起来像这样的使用者(伪代码):
boolean is_done;int other_state;
while(!is_done)
{
//read input
//parse input
//yield input to coroutine
//update is_done and other_state;
}
我们需要抽象局部变量like
is_done
和other_state
,并且需要抽象while循环本身,因为我们的yield
like操作不会使用堆栈。因此,让我们创建一个while循环抽象和相关类:
enum WhileState {BREAK, CONTINUE, YIELD}abstract class WhileLoop<T>
{
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();
}
这里的基本技巧是将 变量移动为 变量,并将作用域块转换为类,这使我们能够在产生返回值之后“重新输入”“循环”。
现在实施我们的生产者
public class SampleProducer : CoroutineProducer<Object>{
private WhileLoop<Object> 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();
}
}
对于其他基本控制流结构,可以采取类似的技巧。理想情况下,您将建立一个包含这些帮助程序类的库,然后使用它们来实现这些简单的接口,这些接口最终将为您提供协同例程的语义。我确信我在这里编写的所有内容都可以得到概括和扩展。
以上是 用Java实现协程 的全部内容, 来源链接: utcz.com/qa/432392.html