7

我一直致力于在 JavaScript 中实现一个非常复杂的系统,该系统需要模拟多线程进程等。在真正的多线程进程(例如内核线程)中,可以通过上下文切换在线程之间切换。这是有效的,因为您可以将当前进程的程序计数器和寄存器存储到一个临时结构中,为其他进程恢复程序计数器和寄存器,然后从您在前一个进程中中断的地方恢复。

我很好奇是否有可能在 JavaScript 中有类似的东西。我目前不知道如何做到这一点,因此一直在使用协作多任务设计系统。特别是,我想在多线程模拟器中运行的任何“函数”都被拆分为一函数。为了执行“函数”,我遍历函数数组,按顺序执行每个函数,同时维护下一个要执行的函数的“程序计数器”。这允许我通过调用数组中的一个函数来模拟上下文切换,等待函数返回,然后切换到需要执行的其他一些函数数组。

我目前的方法有效,但是在这个系统中编写代码很困难。每个函数都必须明确指出何时可以中断,并且由于数组中的函数都是独立的,因此函数不同部分之间的数据通信逻辑很复杂。我希望得到更接近抢先式多任务工作的东西。

我的问题是:是否可以通过外部源暂停和恢复任意 JavaScript 函数的方式运行它?

4

2 回答 2

4

检查StratifiedJS _

于 2011-02-07T07:38:35.357 回答
3

首先,重要的是要提到 JavaScript 是完全单线程的。模拟多线程真的不是要走的路。依赖事件循环会好得多。

如前所述,可以使用网络工作者,但他们并没有真正的跨浏览器合规性,所以我将忽略网络工作者。此外,您不能对 Web 工作者进行任何 DOM 操作。

我想说看看node.js来推理为什么事件循环是多线程的一个很好的替代方案。我相信他很好地解释了为什么它在这个视频中是一个很好的选择。

因此,与其拥有一组函数并对其进行迭代,不如创建一个事件并将一组函数绑定到它们并触发所述事件。在主干.js中可以找到一个非常轻量级的事件实现。

你不能只暂停 JavaScript 中的一个线程,因为只有一个。如果函数中没有点,就无法暂停或恢复函数。

只有一种方法可以模仿这一点。编写一个 JavaScript 解析器,将您精心构建的 JavaScript 分开,并构建一个允许您暂停和恢复 JavaScript 的系统。

以这个函数为例

function(i) {
    j = i + 1;
    console.log(j);
    return foo(j);
}

并将其转换为

var bar = function(i) {
    var r = {};
    var j = i + 1; 
    var f = function() {
         console.log(j);
         var g = function() {
              return foo(j);
         };
         onNext(g, arguments.callee, this, r);
    };
    onNext(f, arguments.callee, this);
    return r;
}

您将需要使用.suspend和扩展功能.resume

Function.prototype.suspend = function() {
     this.__suspended = true;
}

Function.prototype.resume = function() {
     this.__suspended = false;
}

function onNext(callback, function, context, returnObj) {
     if (!function.__suspended) {
          var cb = function() {
              Backbone.Events.unbind("run", cb);
              returnObj.r = callback.call(this);
          }
          Backbone.Events.bind("run", cb);
     }
}

setInterval(function() {
     Backbone.Events.trigger("run");
}, 5);

您还必须将所有引用替换var a = b()

callFunctionAsync(b, context, args, function(return) {
    var a = return;
    ...
});

我会把实施留给你。现在所有函数都返回一个对象r,只有当r.r设置为一个值时它才会“返回”。r.r因此,只需通过检查是否已设置以及是否触发了函数异步回调来检查事件循环是否已“返回” 。

嘿,看看我们有什么。通过在事件循环中运行线程来模拟线程。在代码中本地使用事件循环比通过它模拟线程要好得多。

当您再次绕过事件循环时,基本上让您的函数运行其代码的下一行。并检查在您绕过事件循环时特定的“功能”是否被暂停或恢复。

为了简洁起见,我没有实现将函数的返回冒泡返回到“函数”。这不应该太难模仿。

要么直接使用事件循环,要么使用假线程方法,并让编译器编译你的代码,这样你在编码时它就不会看起来很可怕。

如果你造成死锁,祝你好运。

于 2011-02-07T08:00:15.173 回答