gpt4 book ai didi

java - 我应该为每个线程使用单独的 ScriptEngine 和 CompiledScript 实例吗?

转载 作者:太空宇宙 更新时间:2023-11-04 10:53:32 24 4
gpt4 key购买 nike

我的程序使用Java Scripting API,可以同时评估一些脚本。它们不使用共享脚本对象、绑定(bind)或上下文,但可以使用相同的 ScriptEngine 和 CompiledScript 对象。我发现 Java 8 中的 Oracle Nashorn 实现不是多线程的,ScriptEngineFactory.getParameter('THREADING') 返回 null,文档对此表示:

The engine implementation is not thread safe, and cannot be used to execute scripts concurrently on multiple threads.

这是否意味着我应该为每个线程创建一个单独的 ScriptEngine 实例?此外,文档没有提及 CompiledScript 并发使用,但是:

Each CompiledScript is associated with a ScriptEngine

可以假设 CompiledScript 线程安全性取决于相关的 ScriptEngine,即我应该为 Nashorn 的每个线程使用单独的 CompiledScript 实例。

如果我应该,对于这种(我认为很常见)情况,使用 ThreadLocal、池或其他东西合适的解决方案是什么?

final String script = "...";
final CompiledScript compiled = ((Compilable)scriptEngine).compile(script);
for (int i=0; i<50; i++) {
Thread thread = new Thread () {
public void run() {
try {
scriptEngine.eval(script, new SimpleBindings ()); //is this code thread-safe?
compiled.eval(new SimpleBindings ()); //and this?
}
catch (Exception e) { throw new RuntimeException (e); }
}
};
threads.start();
}

最佳答案

您可以跨线程共享 ScriptEngineCompiledScript 对象。它们是线程安全的。实际上,您应该共享它们,因为单个引擎实例是类缓存和 JavaScript 对象的隐藏类的持有者,因此只有一个引擎实例可以减少重复编译。

您不能共享的是 Bindings 对象。绑定(bind)对象基本上对应于 JavaScript 运行时环境的 Global 对象。引擎以默认的绑定(bind)实例启动,但如果您在多线程环境中使用它,则需要使用 engine.createBindings() 为每个线程获取一个单独的 Bindings 对象(它自己的全局),并在其中评估已编译的脚本。这样您就可以使用相同的代码设置隔离的全局范围。 (当然,您也可以将它们集中起来,或者对它们进行同步,只需确保在一个绑定(bind)实例中工作的线程不超过一个)。一旦将脚本评估为绑定(bind),您就可以随后有效地调用它定义的函数 ((JSObject)bindings.get(fnName).call(this, args...)

如果必须跨线程共享状态,那么至少尝试使其不可变。如果您的对象是不可变的,您不妨将脚本评估为单个 Bindings 实例,然后跨线程使用它(希望调用无副作用的函数)。如果它是可变的,你就必须同步;要么是整个绑定(bind),要么您也可以使用 varsyncFn = Java.synchronized(fn, lockObj) Nashorn 特定的 JS API 来获取在特定对象上同步的 JS 函数的版本。

这假定您跨线程共享单个绑定(bind)。如果您想让多个绑定(bind)共享对象的子集(例如,通过将同一对象放入多个绑定(bind)中),那么您必须以某种方式确保对共享对象的访问是线程安全的。

至于THREADING parameter returning null :是的,最初我们计划不使引擎线程安全(也就是说语言本身不是线程安全的),所以我们选择了 null 值。我们现在可能需要重新评估这一点,因为与此同时我们确实使引擎实例是线程安全的,只是全局范围(绑定(bind))不是(并且永远不会,因为 JavaScript 语言语义)。

关于java - 我应该为每个线程使用单独的 ScriptEngine 和 CompiledScript 实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47544932/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com