2

假设我需要在同一个线程中执行N个任务。这些任务有时可能需要来自外部存储的一些值。我事先不知道哪个任务可能需要这样的值以及何时。一次获取M个值比向外部存储的M个查询中获取相同的M个值要快得多。

请注意,我不能指望任务本身的合作,它们只能被视为 java.lang.Runnable 对象

现在,在我看来,理想的程序看起来像

  1. 循环执行所有任务。如果一个任务请求一个外部值,记住这一点,暂停 任务并切换到下一个。
  2. 一次获取上一步请求的值。
  3. 删除所有已完成的任务(暂停的不计为已完成)。
  4. 如果还有任务,则转到步骤 1,但不是执行任务,而是从挂起状态继续执行。

据我所知,“暂停”和“恢复”某事的唯一方法是从 JVM 堆栈中删除其相关帧,将它们存储在某个地方,然后将它们推回堆栈并让 JVM 继续。

是否有任何标准(不涉及比 JVM 字节码更低级别的黑客攻击)方法来做到这一点?

或者您能否提出另一种可能的方法来实现这一点(除了启动N个线程或使任务以某种方式合作)?

4

3 回答 3

2

可以使用类似quasar的东西通过代理进行堆栈切片。任务的某种程度的合作是有帮助的,但是可以使用 AOP 从外部插入暂停点。

(IMO最好明确说明正在发生的事情(使用例如FutureForkJoinPool)。如果一些纯代码在一个线程上运行了一段时间,然后“神奇地”挂起并跳转到另一个线程,这对于调试或推理可能会非常混乱关于。对于现代语言和库,明确指出异步边界的开销不应该是压倒性的。如果您的任务是根据泛型类型编写的,那么通过 scalaz 之类的东西相当容易Future。但这不符合您的要求给定的要求)。

于 2014-12-01T14:57:21.877 回答
1

如前所述,Quasar正是这样做的(它通常在 M 个线程上调度 N 个纤程,但您可以将 M 设置为 1),使用字节码转换。它甚至为每个任务(又名“光纤”)提供了自己的堆栈跟踪,因此您可以转储它并获得完整的堆栈跟踪,而不会受到任何其他共享线程的任务的干扰。

于 2015-02-17T15:19:28.063 回答
0

那么你可以试试这个

你需要

  1. 一种保存任务当前状态的机制,因为当任务返回时,它的帧将从调用堆栈中弹出。根据返回值或类似的东西,您可以确定天气是否完成,因为您需要从它离开的地方重新执行它,因此您需要保留状态信息。

  2. 为每个任务创建一个请求数据结构。当一个任务想要请求它记录在那里的东西时,数据结构应该支持一个任务可以发出的所有可能的请求。

  3. 将这些 DS 存储在地图中。在循环结束时,您可以查询此 DS 以确定每个任务所需的资源类型。

  4. 获取资源将其放入 DS 中。从任务返回时的状态启动任务。

  5. 任务查询 DS 获取资源。

  6. 当任务想要使用外部资源时,它应该使用这个 DS。

您需要特别考虑设计请求资源的方法,因为当您再次重新执行任务时,您需要自己调用此方法,以便任务可以从它离开的地方执行。

*DS -> 数据结构

希望能帮助到你。

于 2014-12-01T15:42:29.923 回答