了解 worker 与并发

用于桌面平台的 Flash Player 11.4 和更高版本以及 Adobe AIR 13.4 和更高版本

当某应用程序不使用 worker 时,该应用程序的代码在称为执行 线程 的单个线性块的执行步骤中执行。该线程可执行开发人员编写的代码。它还执行作为运行时一部分的大部分代码,尤其是当显示对象的属性更改时更新屏幕的代码。虽然代码用块的形式以方法和类进行编写,但在运行时,代码一次执行一行,就好像其是用一长串步骤编写而成。请考虑下面应用程序执行的步骤假设示例:

  1. 输入帧:运行时调用任意 enterFrame 事件处理函数并一次运行其一个代码

  2. 鼠标事件:用户移动鼠标,并当发生各种 rollover 和 rollout 事件时,运行时调用任意鼠标事件处理函数

  3. 加载完整事件:从 url 中加载 xml 文件的请求返回并带有加载的文件数据。事件处理函数被调用并运行其步骤,读取 xml 内容并从 xml 中创建一组对象。

  4. 鼠标事件:鼠标再次移动,因此运行时调用相关鼠标事件处理函数

  5. 渲染:没有更多事件在等待,因此运行时根据对显示对象所做的任何更改来更新屏幕

  6. 输入帧:循环再次开始

如示例中所述,假设步骤 1-5 在称为帧的单个时间块内按顺序运行。由于它们在单线程中按顺序运行,因此运行时无法中断过程的一个步骤以运行另一个步骤。在每秒 30 帧的帧速率下,运行时有不到三十分之一秒的时间来执行所有这些操作。在许多有足够时间运行代码的示例中,在剩余时间期间运行时只是等待。但是,假设在步骤 3 中加载的 xml 数据非常大,深深嵌入 xml 结构。随着代码在 xml 中循环并创建对象,可以想得到其可能花费比三十分之一秒更长的时间来执行这项工作。在这种情况下,后面的步骤(响应鼠标并刷新屏幕)不会以应有的速度发生。这将由于屏幕刷新不够快速响应用户移动鼠标而导致屏幕冻结和不连贯。

如果所有代码都在同一线程中执行,则只有一种方法可避免临时不连贯和冻结。这便是不执行耗时操作,如在大量数据中循环。ActionScript worker 可提供另一种解决方案。使用 worker,可以在单独的 worker 中执行长时间运行的代码。每个 worker 都在单独线程中运行,因此后台 worker 在其自身线程中执行耗时操作。这样释放了主 worker 的执行线程以刷新屏幕每帧,而不会受到其他工作的阻碍。

这种方法中同时运行多个代码操作的能力称为 并发 。当后台 worker 完成其工作或者处于途中“进行”点时,可以发送主 worker 通知和数据。这样,您可以编写复杂或耗时操作的代码,但可以避免因缺乏用户经验而使屏幕冻结。

Worker 非常有用,因为它们可以减少由于主渲染线程受其他代码阻止而使帧速率下降的可能。但是,worker 需要使用额外系统内存和 CPU,这可能使整体应用程序性能代价昂贵。由于每个 worker 均使用其自身的运行时虚拟机实例,因此即使不重要的 worker 开销也可能很大。当使用 worker 时,请在所有目标平台测试代码,以确保对系统的需求不是太大。Adobe 建议在典型情境下请勿使用超过一个或两个后台 worker。