当前位置: 首页 > 面试题库 >

用Java实现协程

颜新
2023-03-14
问题内容

这个问题与我有关Java中现有协程实现的问题有关。如我所怀疑的,如果事实证明Java中尚没有完整的协程实现,那么实现这些协程将需要什么?

正如我在该问题中所说的,我了解以下内容:

  1. 您可以将“协程”实现为后台的线程/线程池。
  2. 您可以在后台使用JVM字节码来完成棘手的事情,以使协程成为可能。
  3. 所谓的“达芬奇机” JVM实现具有使协程在无需字节码操作的情况下就可以实现的原语。
  4. 也有多种基于JNI的协程方法。

我将依次解决每个人的不足之处。

基于线程的协程

这种“解决方案”是病态的。协程的整个目的是 避免
线程,锁定,内核调度等开销。协程应该轻巧,快速,并且只能在用户空间中执行。根据具有严格限制的全倾斜线程来实现它们会失去所有优势。

JVM字节码操作

该解决方案更实用,尽管很难实现。这大致相当于跳入C语言中的协程库的汇编语言(这是其中的多少个),其优点是您只需要担心一种架构就可以了。

除非您可以找到在不兼容的堆栈上执行相同操作的方法,否则,这将使您只能在完全兼容的JVM堆栈上运行代码(例如,这意味着没有Android)。但是,如果确实找到了解决方法,那么您现在已经将系统复杂性和测试需求提高了一倍。

达芬奇机

达芬奇机很适合实验,但是由于它不是标准的JVM,因此它的功能不会在任何地方都可用。实际上,我怀疑大多数生产环境都将特别禁止使用达芬奇机器。因此,我可以用它来进行出色的实验,但不能用于我希望发布到现实世界中的任何代码。

这也具有类似于上面的JVM字节码操作解决方案的附加问题:在替代堆栈(如Android的堆栈)上将不起作用。

JNI实施

这种解决方案完全没有用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_doneother_state,并且需要抽象while循环本身,因为我们的yieldlike操作不会使用堆栈。因此,让我们创建一个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();
    }
}

对于其他基本控制流结构,可以采取类似的技巧。理想情况下,您将建立一个包含这些帮助程序类的库,然后使用它们来实现这些简单的接口,这些接口最终将为您提供协同例程的语义。我确信我在这里编写的所有内容都可以得到概括和扩展。



 类似资料:
  • 本文向大家介绍用Python实现协同过滤的教程,包括了用Python实现协同过滤的教程的使用技巧和注意事项,需要的朋友参考一下 协同过滤 在 用户 —— 物品(user - item)的数据关系下很容易收集到一些偏好信息(preference),比如评分。利用这些分散的偏好信息,基于其背后可能存在的关联性,来为用户推荐物品的方法,便是协同过滤,或称协作型过滤(collaborative filte

  • 本文向大家介绍golang 40行代码实现通用协程池,包括了golang 40行代码实现通用协程池的使用技巧和注意事项,需要的朋友参考一下 代码仓库 goroutine-pool golang的协程管理 golang协程机制很方便的解决了并发编程的问题,但是协程并不是没有开销的,所以也需要适当限制一下数量。 不使用协程池的代码(示例代码使用chan实现,代码略啰嗦) 需要实现的需求有两个: 限制最

  • 问题内容: 我尝试用Java的编程思想实现OAuth,但失败了。我不知道为什么,但是我的代码不起作用。每次运行程序时,都会引发IOException,其原因为“ java.io.IOException:服务器返回的HTTP响应代码:401”(401表示未授权)。我仔细查看了文档,但是我真的不明白为什么它不起作用。我想使用的OAuth提供程序是twitter,我也在其中注册了我的应用程序。 在此先感

  • 问题内容: 因此,我正在开发一个简单的Java应用程序,该应用程序允许用户输入图像作为查询,并使该应用程序将其与图像数据库进行比较(基本上只不过是不同图像的目录)。我基本上是在研究几种图像相似性测量技术,以找出哪些适合比较汽车图片。 我一直在做一些阅读,除了FFT / SSIM之外,我还阅读了SIFT算法可以产生非常好的结果。但是,作为只有大约一年的Java基本经验的人,老实说,我不确定我是否有足

  • 问题内容: 这是一个通用的问题。我并不是在寻找最佳答案,而是希望您表达自己喜欢的做法。 我想用Java实现网络协议(但这是一个相当普遍的问题,我在C ++中也遇到了同样的问题),这不是我第一次这样做,这不是第一次。但是我认为我缺少实现它的好方法。实际上,通常所有这些都是关于在主机之间交换文本消息和一些字节缓冲区,存储状态并等待下一条消息到来的。问题是,我通常会遇到很多麻烦,如果if语句对不同的状态

  • 问题内容: 好的,这是个大问题。我有一个用ObjC(this)编写的库。在那里,我们有一个已定义的协议。当我尝试在快速文件中使用它时,我经常得到: 类型“ XXX”不符合协议“ XXX” 为简化起见,我组成了一个测试项目-应该将其创建为Swift项目。 然后使用以下协议在内部创建ObjC头文件(我称其为StupidProtocol.h)(请注意,每个名称和值都应与给定的值完全匹配,包括大写/小写)