gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 20:30:24 27 4
gpt4 key购买 nike

我的程序使用 Java Scripting API 并且可以同时评估一些脚本。它们不使用共享脚本对象、绑定(bind)或上下文,但可以使用相同的 ScriptEngineCompiledScript 对象。我看到 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 对象。 bindings 对象基本上对应于 JavaScript 运行时环境的 Global 对象。引擎从默认绑定(bind)实例开始,但如果在多线程环境中使用它,则需要使用 engine.createBindings() 为每个线程获取单独的 Bindings 对象——它自己的全局对象,并且将编译后的脚本评估到其中。这样,您将使用相同的代码设置隔离的全局范围。 (当然,您也可以将它们池化,或在它们上同步,只要确保在一个绑定(bind)实例中工作的线程不超过一个)。将脚本评估为绑定(bind)后,您可以随后有效地调用它定义的函数 ((JSObject)bindings.get(fnName).call(this, args...)

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

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

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

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

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