当前位置: 首页 > 面试题库 >

是否应该在每个线程中使用单独的ScriptEngine和CompiledScript实例?

濮赤岩
2023-03-14
问题内容

我的程序使用Java Scripting
API,并且可以同时评估某些脚本。他们不使用共享脚本对象,绑定或上下文,但可以使用ScriptEngineCompiledScript对象。我看到,在Java的甲骨文8实施犀牛不是多线程的,ScriptEngineFactory.getParameter('THREADING')回报率null约该文件说:

引擎实现不是线程安全的,并且不能用于在多个线程上同时执行脚本。

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

每个CompiledScript与一个ScriptEngine相关联

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

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

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

前提是您在线程之间共享单个绑定。如果要让多个绑定共享对象的子集(例如,通过将同一个对象放入多个绑定中),则必须以某种方式处理确保对共享对象的访问本身是线程安全的。

至于THREADING返回null的参数:是的,最初我们计划不使引擎具有线程安全性(假设语言本身不是线程安全的),所以我们选择了null值。我们现在可能需要重新评估,因为与此同时我们做到了,以便引擎实例是线程安全的,只是全局范围(绑定)不是(并且永远不会,因为JavaScript语言语义)。



 类似资料:
  • 我的程序使用Java脚本API,可以同时评估一些脚本。它们不使用共享脚本对象、绑定或上下文,但可以使用相同的和对象。我发现Java8中的OracleNashorn实现不是多线程的,返回,文档中说: 引擎实现不是线程安全的,不能用于在多个线程上并发执行脚本。 这是否意味着我应该为每个线程创建一个单独的实例?此外,文档中没有提到并发使用,而是: 每个已编译脚本都与一个脚本引擎相关联 可以假设线程安全依

  • 我写了以下代码: 我只使用了一个useState在一个对象中存储“name”、“link”、“error”等属性。因为我想将FormObj和ValidateLink的逻辑保持在一起。所有三个属性仅使用一个useEffect。因此,我认为最好将所有三个属性都保留在useState中,而不是创建3个不同的useState。 但是我的经理和技术架构师告诉我要为每个属性创建3个useState,一个use

  • 问题内容: 我在处理pyGTK应用程序时遇到一些问题。我给线程一些时间来完成其任务,如果有问题,我还是继续继续,只是警告用户。但是,一旦我继续,该线程就会停止,直到调用gtk.main_quit为止。这让我感到困惑。 相关代码: .................................... 问题答案: 首先,不要继承,使用。 其次,很可能导致您明显的阻塞的原因是它采用了一个默认值为的参

  • 给stackoverflow社区的人们。我正在寻找一些帮助,以解决HikariCP连接池面临的问题。 高级:我正在尝试使用线程池创建多个线程,我的计划是为每个工作线程提供独立于HikariCP的连接,但HikariCP所做的是在多个线程之间共享一个公共连接。我正在使用 以检索DB连接。现在,当我关闭一个连接时,我在其他线程中看到问题,说连接关闭了,线程正在处理的批次记录被丢弃。 以下是我的日志文件

  • 在Kafka-manager github页面中写道: 最低配置是用于kafka管理器状态的zoo门主机。这可以在conf目录的application.conf文件中找到。相同的文件将打包在分发zip文件中;您可以在所需服务器上解压缩文件后修改设置。 Kafka-manager . ZK hosts = " my . zookeeper . host . com:2181 "您可以通过逗号分隔来指

  • 当我调用foo()时,这个方法是否在单独的线程上运行?