Подтвердить что ты не робот

Rhino и одновременный доступ к javax.script.ScriptEngine

Я использую Rhino 1.6r2 через API javax.script. Я знаю, что двигатель Rhino утверждает, что MULTITHREADED: "Реализация ядра внутренне поточно-безопасна, и скрипты могут выполняться одновременно, хотя эффекты script выполнение в одном потоке может быть видимым для скриптов в других потоках".

Что я хотел бы знать, в каких точных условиях эффекты одного из script выполнялись бы видимыми для другого? В моем коде я иногда повторно использую объект ScriptEngine, но для каждого выполнения я создаю новый SimpleBindings и передаю его в eval(String, Bindings). С этим соглашением существует ли способ, которым внутреннее состояние может протекать от одного исполнения к другому? Если да, то как?

Здесь очень информативный ответ, но он не совсем скажет мне, что мне нужно знать.

4b9b3361

Ответ 1

Да, JSR223 не указал, как переменные в языке script должны быть связаны с заданным Bindings. Поэтому вполне возможно, что разработчики выбирают сохранение глобальных переменных сферы в экземпляре двигателя и повторно используют его даже при разных Bindings при оценке script.

Например, привязка JRuby JSR223 имеет один режим, работающий таким образом

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class Jsr223Binding {


    private Jsr223Binding() throws ScriptException {
        System.setProperty("org.jruby.embed.localvariable.behavior", "transient");
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("jruby");
        ScriptContext ctx1 = new SimpleScriptContext();
        ScriptContext ctx2 = new SimpleScriptContext();
        engine.eval("$foo = 5\nputs $foo", ctx1);
        engine.eval("puts $foo", ctx2);
    }

    public static void main(String[] args) throws ScriptException {
        new Jsr223Binding();
    }
}

Ответ 2

Пакет javax.script является потокобезопасным, но если ваш script нет, вы можете иметь проблемы concurrency. Глобальные переменные внутри script видны для всех потоков. Таким образом, избегать использования глобальных переменных внутри ваших функций javascript

Сейчас я сталкиваюсь с этой проблемой. Мой javascript выглядит следующим образом:

function run(){
    regex = 0;
    regex += 1;
    return regex;
}

И я запускаю его внутри ThreadPool (4) 10.000 раз и печатаю результат.

for (int i = 0; i <= 10000; i++){
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Double result = (Double) invocable.invokeFunction("run");
                    System.out.println(result);
                } catch (Exception e) {}
            }
        });
    }

Это часть вывода:

1.0
2.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
2.0
1.0
1.0
0.0